basic/mach/
runtime.rs

1extern crate rand;
2use super::*;
3use crate::error;
4use crate::lang::{Error, Line, LineNumber, MaxValue};
5use std::collections::HashMap;
6use std::convert::TryFrom;
7use std::ops::{Range, RangeInclusive};
8use std::rc::Rc;
9use std::sync::Arc;
10
11type Result<T> = std::result::Result<T, Error>;
12
13const INTRO: &str = "64K BASIC";
14const PROMPT: &str = "READY.";
15
16/// ## Virtual machine
17
18pub struct Runtime {
19    prompt: String,
20    listing: Listing,
21    dirty: bool,
22    program: Program,
23    pc: Address,
24    tr: LineNumber,
25    tron: bool,
26    entry_address: Address,
27    stack: RuntimeStack,
28    vars: Var,
29    state: State,
30    cont: State,
31    cont_pc: Address,
32    print_col: usize,
33    rand: (u32, u32, u32),
34    functions: HashMap<Rc<str>, (usize, Address)>,
35}
36
37/// ## Events for the user interface
38
39#[derive(Debug)]
40pub enum Event {
41    Errors(Arc<Vec<Error>>),
42    Input(String, bool),
43    Print(String),
44    List((String, Vec<Range<usize>>)),
45    Running,
46    Stopped,
47    Load(String),
48    Run(String),
49    Save(String),
50    Cls,
51    Inkey,
52}
53
54#[derive(Debug)]
55enum State {
56    Intro,
57    Stopped,
58    Listing(RangeInclusive<LineNumber>),
59    RuntimeError(Error),
60    Running,
61    Input,
62    InputRedo,
63    InputRunning,
64    Interrupt,
65    Inkey,
66}
67
68impl Default for Runtime {
69    fn default() -> Self {
70        Runtime {
71            prompt: PROMPT.into(),
72            listing: Listing::default(),
73            dirty: false,
74            program: Program::default(),
75            pc: 0,
76            tr: None,
77            tron: false,
78            entry_address: 1,
79            stack: Stack::new("STACK OVERFLOW"),
80            vars: Var::new(),
81            state: State::Intro,
82            cont: State::Stopped,
83            cont_pc: 0,
84            print_col: 0,
85            rand: (1, 1, 1),
86            functions: HashMap::default(),
87        }
88    }
89}
90
91impl Runtime {
92    /// Enters a line of BASIC or INPUT.
93    /// Returns true if good candidate for history.
94    pub fn enter(&mut self, string: &str) -> bool {
95        if let State::Input = self.state {
96            self.enter_input(string);
97            self.print_col = 0;
98            return true;
99        }
100        if let State::Inkey = self.state {
101            self.enter_inkey(string);
102            return false;
103        }
104        debug_assert!(matches!(self.state, State::Stopped | State::Intro));
105        if string.len() > MAX_LINE_LEN {
106            self.state = State::RuntimeError(error!(LineBufferOverflow));
107            return false;
108        }
109        let line = Line::new(string);
110        if line.is_direct() {
111            if line.is_empty() {
112                false
113            } else {
114                self.enter_direct(line);
115                true
116            }
117        } else {
118            self.enter_indirect(line);
119            false
120        }
121    }
122
123    fn enter_direct(&mut self, line: Line) {
124        if self.dirty {
125            self.program.clear();
126            self.program.compile(self.listing.lines());
127            self.dirty = false;
128        }
129        self.program.compile(&line);
130        let (pc, indirect_errors, direct_errors) = self.program.link();
131        self.pc = pc;
132        self.tr = None;
133        self.entry_address = pc;
134        self.listing.indirect_errors = indirect_errors;
135        self.listing.direct_errors = direct_errors;
136        self.state = State::Running;
137    }
138
139    fn enter_indirect(&mut self, line: Line) {
140        self.cont = State::Stopped;
141        if line.is_empty() {
142            self.dirty = self.listing.remove(line.number()).is_some();
143        } else {
144            self.listing.insert(line);
145            self.dirty = true;
146        }
147    }
148
149    fn enter_inkey(&mut self, mut string: &str) {
150        if string.len() > MAX_LINE_LEN {
151            string = "";
152        }
153        if let Err(error) = self.stack.push(Val::String(string.into())) {
154            self.clear();
155            self.state = State::RuntimeError(error);
156        }
157        self.state = State::Running;
158    }
159
160    fn enter_input(&mut self, string: &str) {
161        if string.len() > MAX_LINE_LEN {
162            self.state = State::InputRedo;
163            return;
164        }
165        if let Err(error) = self.do_input(string) {
166            self.clear();
167            self.state = State::RuntimeError(error);
168            debug_assert!(false, "BAD INPUT STACK");
169        }
170    }
171
172    fn do_input(&mut self, string: &str) -> Result<()> {
173        let len = match self.stack.last() {
174            Some(Val::Integer(n)) => *n as usize,
175            _ => return Err(error!(InternalError)),
176        };
177        let mut vec_val: Vec<Val> = vec![];
178        if len <= 1 {
179            vec_val.push(Val::String(string.into()));
180        } else {
181            let mut start: usize = 0;
182            let mut in_quote = false;
183            for (index, ch) in string.char_indices() {
184                match ch {
185                    '"' => {
186                        in_quote = !in_quote;
187                    }
188                    ',' if !in_quote => {
189                        vec_val.push(Val::String(string[start..index].into()));
190                        start = index + 1;
191                    }
192                    _ => {}
193                }
194            }
195            vec_val.push(Val::String(string[start..].into()));
196            if len as usize != vec_val.len() {
197                self.state = State::InputRedo;
198                return Ok(());
199            }
200        }
201        self.stack.push(Val::Return(self.pc))?;
202        while let Some(v) = vec_val.pop() {
203            self.stack.push(v)?;
204        }
205        self.state = State::InputRunning;
206        Ok(())
207    }
208
209    fn ready_prompt(&mut self) -> Option<Event> {
210        if self.entry_address != 0 {
211            self.entry_address = 0;
212            let mut s = String::new();
213            if self.print_col > 0 {
214                s.push('\n');
215                self.print_col = 0;
216            }
217            if !self.prompt.is_empty() {
218                s.push_str(&self.prompt);
219                s.push('\n');
220            }
221            return Some(Event::Print(s));
222        };
223        None
224    }
225
226    /// Obtain a thread-safe Listing for saving and line completion.
227    pub fn get_listing(&self) -> Listing {
228        self.listing.clone()
229    }
230
231    /// Set a new listing. Used to load a program.
232    pub fn set_listing(&mut self, listing: Listing, run: bool) {
233        self.r#new_();
234        self.listing = listing;
235        if run {
236            self.enter("RUN");
237        }
238    }
239
240    /// Set a prompt instead of the default "READY."
241    pub fn set_prompt(&mut self, prompt: &str) {
242        self.prompt = prompt.into();
243    }
244
245    /// Interrupt the program. Displays `BREAK` error.
246    pub fn interrupt(&mut self) {
247        self.cont = State::Interrupt;
248        std::mem::swap(&mut self.state, &mut self.cont);
249        self.cont_pc = self.pc;
250        if self.pc >= self.entry_address {
251            self.cont = State::Stopped;
252            self.stack.clear();
253        }
254    }
255
256    /// Use a large number for iterations but not so much
257    /// that interrupts aren't responsive.
258    pub fn execute(&mut self, iterations: usize) -> Event {
259        fn line_number(this: &Runtime) -> LineNumber {
260            let mut pc = this.pc;
261            if pc > 0 {
262                pc -= 1
263            }
264            this.program.line_number_for(pc)
265        }
266        match &self.state {
267            State::Intro => {
268                self.state = State::Stopped;
269                let mut s = INTRO.to_string();
270                if let Some(version) = option_env!("CARGO_PKG_VERSION") {
271                    s.push(' ');
272                    s.push_str(version);
273                }
274                #[cfg(debug_assertions)]
275                s.push_str("+debug");
276                s.push('\n');
277                return Event::Print(s);
278            }
279            State::Stopped => match self.ready_prompt() {
280                Some(e) => return e,
281                None => return Event::Stopped,
282            },
283            State::Interrupt => {
284                self.state = State::RuntimeError(error!(Break, line_number(&self)));
285            }
286            State::Listing(range) => {
287                let mut range = range.clone();
288                if let Some((string, columns)) = self.listing.list_line(&mut range) {
289                    self.state = State::Listing(range);
290                    return Event::List((string, columns));
291                } else {
292                    self.state = State::Running;
293                }
294            }
295            State::Input => match self.execute_input() {
296                Ok(event) => return event,
297                Err(error) => {
298                    self.state = State::RuntimeError(error.in_line_number(line_number(&self)))
299                }
300            },
301            State::InputRedo => {
302                self.state = State::Input;
303                return Event::Errors(Arc::new(vec![error!(RedoFromStart)]));
304            }
305            State::InputRunning | State::Running => {
306                if !self.listing.direct_errors.is_empty() {
307                    self.state = State::Stopped;
308                    return Event::Errors(Arc::clone(&self.listing.direct_errors));
309                }
310            }
311            State::Inkey | State::RuntimeError(_) => {}
312        }
313        if let State::RuntimeError(_) = self.state {
314            if self.print_col > 0 {
315                self.print_col = 0;
316                return Event::Print('\n'.to_string());
317            }
318            let mut state = State::Stopped;
319            std::mem::swap(&mut self.state, &mut state);
320            if let State::RuntimeError(error) = state {
321                return Event::Errors(Arc::new(vec![error]));
322            }
323        }
324        debug_assert!(matches!(self.state, State::Running | State::InputRunning));
325        match self.execute_loop(iterations) {
326            Ok(event) => {
327                if let State::Stopped = self.state {
328                    if let Event::Stopped = event {
329                        if let Some(event) = self.ready_prompt() {
330                            return event;
331                        }
332                    }
333                }
334                event
335            }
336            Err(error) => {
337                if let State::InputRunning = self.state {
338                    loop {
339                        match self.stack.pop() {
340                            Err(_) => break,
341                            Ok(Val::Return(addr)) => {
342                                self.pc = addr;
343                                break;
344                            }
345                            _ => continue,
346                        }
347                    }
348                    self.state = State::InputRedo;
349                } else {
350                    self.cont = State::RuntimeError(error.in_line_number(line_number(&self)));
351                    std::mem::swap(&mut self.cont, &mut self.state);
352                    self.cont_pc = self.pc;
353                    if self.pc >= self.entry_address || self.stack.is_full() {
354                        self.stack.clear();
355                        self.cont = State::Stopped;
356                    }
357                }
358                Event::Running
359            }
360        }
361    }
362
363    fn execute_input(&mut self) -> Result<Event> {
364        let len = self.stack.pop()?;
365        let caps = self.stack.pop()?;
366        let mut prompt = match self.stack.last() {
367            Some(Val::String(s)) => s.to_string(),
368            _ => return Err(error!(InternalError)),
369        };
370        prompt.push('?');
371        prompt.push(' ');
372        let is_caps = match caps {
373            Val::Integer(i) if i == 0 => false,
374            _ => true,
375        };
376        self.stack.push(caps)?;
377        self.stack.push(len)?;
378        self.print_col = 0;
379        Ok(Event::Input(prompt, is_caps))
380    }
381
382    #[allow(clippy::cognitive_complexity)]
383    fn execute_loop(&mut self, iterations: usize) -> Result<Event> {
384        let has_indirect_errors = !self.listing.indirect_errors.is_empty();
385        for _ in 0..iterations {
386            if self.tron {
387                let tr = self.program.line_number_for(self.pc);
388                if tr != self.tr {
389                    self.tr = tr;
390                    if let Some(num) = self.tr {
391                        let num = format!("[{}]", num);
392                        self.print_col += num.len();
393                        return Ok(Event::Print(num));
394                    }
395                }
396            }
397            let op = match self.program.get(self.pc) {
398                Some(v) => v,
399                None => return Err(error!(InternalError; "INVALID PC ADDRESS")),
400            };
401            self.pc += 1;
402            match op {
403                Opcode::Literal(val) => self.stack.push(val.clone())?,
404                Opcode::Pop(var_name) => self.vars.store(&var_name, self.stack.pop()?)?,
405                Opcode::Push(var_name) => self.stack.push(self.vars.fetch(&var_name))?,
406                Opcode::PopArr(var_name) => {
407                    let vec = self.stack.pop_vec()?;
408                    let val = self.stack.pop()?;
409                    self.vars.store_array(&var_name, vec, val)?;
410                }
411                Opcode::PushArr(var_name) => {
412                    let vec = self.stack.pop_vec()?;
413                    let val = self.vars.fetch_array(&var_name, vec)?;
414                    self.stack.push(val)?;
415                }
416                Opcode::DimArr(var_name) => {
417                    let vec = self.stack.pop_vec()?;
418                    self.vars.dimension_array(&var_name, vec)?;
419                }
420                Opcode::EraseArr(var_name) => self.vars.erase_array(&var_name)?,
421                Opcode::IfNot(addr) => {
422                    if match self.stack.pop()? {
423                        Val::Return(_) | Val::String(_) | Val::Next(_) => {
424                            return Err(error!(TypeMismatch))
425                        }
426                        Val::Integer(n) => n == 0,
427                        Val::Single(n) => n == 0.0,
428                        Val::Double(n) => n == 0.0,
429                    } {
430                        self.pc = addr;
431                    }
432                }
433                Opcode::Jump(addr) => {
434                    self.pc = addr;
435                    if has_indirect_errors && self.pc < self.entry_address {
436                        self.state = State::Stopped;
437                        self.cont = State::Stopped;
438                        return Ok(Event::Errors(Arc::clone(&self.listing.indirect_errors)));
439                    }
440                }
441                Opcode::Clear => self.r#clear(),
442                Opcode::Cls => return self.r#cls(),
443                Opcode::Cont => {
444                    if let Some(event) = self.r#cont()? {
445                        return Ok(event);
446                    }
447                }
448                Opcode::Def(var_name) => self.r#def(var_name)?,
449                Opcode::Defdbl => self.r#defdbl()?,
450                Opcode::Defint => self.r#defint()?,
451                Opcode::Defsng => self.r#defsng()?,
452                Opcode::Defstr => self.r#defstr()?,
453                Opcode::Delete => return self.r#delete(),
454                Opcode::End => return Ok(self.r#end()),
455                Opcode::Fn(var_name) => self.r#fn(var_name)?,
456                Opcode::Input(var_name) => {
457                    if let Some(event) = self.r#input(var_name)? {
458                        return Ok(event);
459                    }
460                }
461                Opcode::LetMid => self.r#letmid()?,
462                Opcode::List => return self.r#list(),
463                Opcode::Load => return self.r#load(),
464                Opcode::LoadRun => return self.r#loadrun(),
465                Opcode::New => return Ok(self.r#new_()),
466                Opcode::On => self.r#on()?,
467                Opcode::Next(var_name) => self.r#next(var_name)?,
468                Opcode::Print => return self.r#print(),
469                Opcode::Read => self.r#read()?,
470                Opcode::Renum => return self.r#renum(),
471                Opcode::Restore(addr) => self.r#restore(addr)?,
472                Opcode::Return => self.r#return()?,
473                Opcode::Save => return self.r#save(),
474                Opcode::Stop => return Err(error!(Break)),
475                Opcode::Swap => self.r#swap()?,
476                Opcode::Troff => self.r#troff(),
477                Opcode::Tron => self.r#tron(),
478
479                Opcode::Neg => self.stack.pop_1_push(&Operation::negate)?,
480                Opcode::Pow => self.stack.pop_2_push(&Operation::power)?,
481                Opcode::Mul => self.stack.pop_2_push(&Operation::multiply)?,
482                Opcode::Div => self.stack.pop_2_push(&Operation::divide)?,
483                Opcode::DivInt => self.stack.pop_2_push(&Operation::divint)?,
484                Opcode::Mod => self.stack.pop_2_push(&Operation::remainder)?,
485                Opcode::Add => self.stack.pop_2_push(&Operation::sum)?,
486                Opcode::Sub => self.stack.pop_2_push(&Operation::subtract)?,
487                Opcode::Eq => self.stack.pop_2_push(&Operation::equal)?,
488                Opcode::NotEq => self.stack.pop_2_push(&Operation::not_equal)?,
489                Opcode::Lt => self.stack.pop_2_push(&Operation::less)?,
490                Opcode::LtEq => self.stack.pop_2_push(&Operation::less_equal)?,
491                Opcode::Gt => self.stack.pop_2_push(&Operation::greater)?,
492                Opcode::GtEq => self.stack.pop_2_push(&Operation::greater_equal)?,
493                Opcode::Not => self.stack.pop_1_push(&Operation::not)?,
494                Opcode::And => self.stack.pop_2_push(&Operation::and)?,
495                Opcode::Or => self.stack.pop_2_push(&Operation::or)?,
496                Opcode::Xor => self.stack.pop_2_push(&Operation::xor)?,
497                Opcode::Imp => self.stack.pop_2_push(&Operation::imp)?,
498                Opcode::Eqv => self.stack.pop_2_push(&Operation::eqv)?,
499
500                Opcode::Abs => self.stack.pop_1_push(&Function::abs)?,
501                Opcode::Asc => self.stack.pop_1_push(&Function::asc)?,
502                Opcode::Atn => self.stack.pop_1_push(&Function::atn)?,
503                Opcode::Cdbl => self.stack.pop_1_push(&Function::cdbl)?,
504                Opcode::Chr => self.stack.pop_1_push(&Function::chr)?,
505                Opcode::Cint => self.stack.pop_1_push(&Function::cint)?,
506                Opcode::Cos => self.stack.pop_1_push(&Function::cos)?,
507                Opcode::Csng => self.stack.pop_1_push(&Function::csng)?,
508                Opcode::Date => self.stack.push(Function::date()?)?,
509                Opcode::Exp => self.stack.pop_1_push(&Function::exp)?,
510                Opcode::Fix => self.stack.pop_1_push(&Function::fix)?,
511                Opcode::Hex => self.stack.pop_1_push(&Function::hex)?,
512                Opcode::Inkey => {
513                    self.state = State::Inkey;
514                    return Ok(Event::Inkey);
515                }
516                Opcode::Instr => {
517                    let vec = self.stack.pop_vec()?;
518                    self.stack.push(Function::instr(vec)?)?;
519                }
520                Opcode::Int => self.stack.pop_1_push(&Function::int)?,
521                Opcode::Left => self.stack.pop_2_push(&Function::left)?,
522                Opcode::Len => self.stack.pop_1_push(&Function::len)?,
523                Opcode::Log => self.stack.pop_1_push(&Function::log)?,
524                Opcode::Mid => {
525                    let vec = self.stack.pop_vec()?;
526                    self.stack.push(Function::mid(vec)?)?;
527                }
528                Opcode::Oct => self.stack.pop_1_push(&Function::oct)?,
529                Opcode::Pos => {
530                    let _val = self.stack.pop_vec()?;
531                    self.stack.push(Function::pos(self.print_col)?)?;
532                }
533                Opcode::Right => self.stack.pop_2_push(&Function::right)?,
534                Opcode::Rnd => {
535                    let vec = self.stack.pop_vec()?;
536                    self.stack.push(Function::rnd(&mut self.rand, vec)?)?;
537                }
538                Opcode::Spc => self.stack.pop_1_push(&Function::spc)?,
539                Opcode::Sgn => self.stack.pop_1_push(&Function::sgn)?,
540                Opcode::Sin => self.stack.pop_1_push(&Function::sin)?,
541                Opcode::Sqr => self.stack.pop_1_push(&Function::sqr)?,
542                Opcode::Str => self.stack.pop_1_push(&Function::str)?,
543                Opcode::String => self.stack.pop_2_push(&Function::string)?,
544                Opcode::Tab => {
545                    let val = self.stack.pop()?;
546                    self.stack.push(Function::tab(self.print_col, val)?)?;
547                }
548                Opcode::Tan => self.stack.pop_1_push(&Function::tan)?,
549                Opcode::Time => self.stack.push(Function::time()?)?,
550                Opcode::Val => self.stack.pop_1_push(&Function::val)?,
551            }
552        }
553        Ok(Event::Running)
554    }
555
556    fn r#clear(&mut self) {
557        self.rand = (
558            (rand::random::<u32>() & 0x_00FF_FFFF) + 1,
559            (rand::random::<u32>() & 0x_00FF_FFFF) + 1,
560            (rand::random::<u32>() & 0x_00FF_FFFF) + 1,
561        );
562        self.program.restore_data(0);
563        self.stack.clear();
564        self.vars.clear();
565        self.functions.clear();
566        self.cont = State::Stopped;
567    }
568
569    fn r#cls(&mut self) -> Result<Event> {
570        Ok(Event::Cls)
571    }
572
573    fn r#cont(&mut self) -> Result<Option<Event>> {
574        if let State::Stopped = self.cont {
575            return Err(error!(CantContinue));
576        }
577        if let State::Running = self.state {
578            self.state = State::Stopped;
579            std::mem::swap(&mut self.cont, &mut self.state);
580            self.pc = self.cont_pc;
581        } else {
582            return Err(error!(CantContinue));
583        }
584        if let State::Running = self.state {
585            Ok(None)
586        } else {
587            Ok(Some(Event::Running))
588        }
589    }
590
591    fn r#def(&mut self, fn_name: Rc<str>) -> Result<()> {
592        if self.pc >= self.entry_address {
593            Err(error!(IllegalDirect))
594        } else if let Val::Integer(len) = self.stack.pop()? {
595            self.functions.insert(fn_name, (len as usize, self.pc + 1));
596            Ok(())
597        } else {
598            Err(error!(InternalError))
599        }
600    }
601
602    fn r#defdbl(&mut self) -> Result<()> {
603        let (from, to) = self.stack.pop_2()?;
604        self.vars.defdbl(from, to)
605    }
606
607    fn r#defint(&mut self) -> Result<()> {
608        let (from, to) = self.stack.pop_2()?;
609        self.vars.defint(from, to)
610    }
611
612    fn r#defsng(&mut self) -> Result<()> {
613        let (from, to) = self.stack.pop_2()?;
614        self.vars.defsng(from, to)
615    }
616
617    fn r#defstr(&mut self) -> Result<()> {
618        let (from, to) = self.stack.pop_2()?;
619        self.vars.defstr(from, to)
620    }
621
622    fn r#delete(&mut self) -> Result<Event> {
623        let (from, to) = self.stack.pop_2()?;
624        let from = LineNumber::try_from(from)?;
625        let to = LineNumber::try_from(to)?;
626        if from == Some(0) && to == Some(LineNumber::max_value()) {
627            return Err(error!(IllegalFunctionCall));
628        }
629        if self.listing.remove_range(from..=to) {
630            self.dirty = true;
631            self.state = State::Stopped;
632        }
633        Ok(self.r#end())
634    }
635
636    fn r#end(&mut self) -> Event {
637        self.cont = State::Stopped;
638        std::mem::swap(&mut self.cont, &mut self.state);
639        self.cont_pc = self.pc;
640        if self.pc >= self.entry_address {
641            self.cont = State::Stopped;
642            self.stack.clear();
643        }
644        Event::Stopped
645    }
646
647    fn r#fn(&mut self, fn_name: Rc<str>) -> Result<()> {
648        let mut args = self.stack.pop_vec()?;
649        if let Some((arity, addr)) = self.functions.get(&fn_name) {
650            if *arity == args.len() {
651                self.stack.push(Val::Return(self.pc))?;
652                for arg in args.drain(..).rev() {
653                    self.stack.push(arg)?;
654                }
655                self.pc = *addr;
656                Ok(())
657            } else {
658                Err(error!(IllegalFunctionCall; "WRONG NUMBER OF ARGUMENTS"))
659            }
660        } else {
661            Err(error!(UndefinedUserFunction))
662        }
663    }
664
665    fn r#input(&mut self, var_name: Rc<str>) -> Result<Option<Event>> {
666        if let State::Running = self.state {
667            self.state = State::Input;
668            self.pc -= 1;
669            return Ok(Some(Event::Running));
670        } else if let State::InputRunning = self.state {
671            if var_name.is_empty() {
672                self.state = State::Running;
673                self.stack.pop()?;
674                self.stack.pop()?;
675                self.stack.pop()?;
676                self.stack.pop()?;
677                return Ok(None);
678            } else if let Val::String(field) = self.stack.pop()? {
679                let mut field = field.trim();
680                if var_name.ends_with('$') {
681                    if field.len() >= 2 && field.starts_with('"') && field.ends_with('"') {
682                        field = &field[1..field.len() - 1];
683                    }
684                    self.stack.push(Val::String(field.into()))?;
685                } else if field.is_empty() {
686                    self.stack.push(Val::Integer(0))?;
687                } else {
688                    self.stack.push(Val::from(field))?;
689                }
690                return Ok(None);
691            }
692        }
693        debug_assert!(false, "input stack corrupt");
694        Err(error!(InternalError))
695    }
696
697    fn r#letmid(&mut self) -> Result<()> {
698        let pos = usize::try_from(self.stack.pop()?)?;
699        let mut len = usize::try_from(self.stack.pop()?)?;
700        let ins_string = Rc::<str>::try_from(self.stack.pop()?)?;
701        if pos == 0 {
702            return Err(error!(IllegalFunctionCall; "POSITION IS ZERO"));
703        }
704        let orig_string = Rc::<str>::try_from(self.stack.pop()?)?;
705        let mut ins = ins_string.chars();
706        let mut s = String::default();
707        for (index, ch) in orig_string.chars().enumerate() {
708            if index + 1 >= pos && len > 0 {
709                len -= 1;
710                if let Some(ch) = ins.next() {
711                    s.push(ch);
712                    continue;
713                }
714            }
715            s.push(ch)
716        }
717        self.stack.push(Val::String(s.into()))?;
718        Ok(())
719    }
720
721    fn r#list(&mut self) -> Result<Event> {
722        let (from, to) = self.stack.pop_2()?;
723        let from = LineNumber::try_from(from)?;
724        let to = LineNumber::try_from(to)?;
725        self.state = State::Listing(from..=to);
726        Ok(Event::Running)
727    }
728
729    fn r#load(&mut self) -> Result<Event> {
730        match self.stack.pop()? {
731            Val::String(s) => {
732                self.r#end();
733                if self.pc < self.entry_address {
734                    Err(error!(IllegalDirect))
735                } else {
736                    Ok(Event::Load(s.to_string()))
737                }
738            }
739            _ => Err(error!(TypeMismatch)),
740        }
741    }
742
743    fn r#loadrun(&mut self) -> Result<Event> {
744        match self.stack.pop()? {
745            Val::String(s) => {
746                self.r#end();
747                Ok(Event::Run(s.to_string()))
748            }
749            _ => Err(error!(TypeMismatch)),
750        }
751    }
752
753    fn r#new_(&mut self) -> Event {
754        self.r#clear();
755        self.listing.clear();
756        self.dirty = true;
757        self.state = State::Stopped;
758        self.tron = false;
759        Event::Stopped
760    }
761
762    fn r#next(&mut self, next_name: Rc<str>) -> Result<()> {
763        loop {
764            let next = match self.stack.pop() {
765                Ok(Val::Next(addr)) => addr,
766                Ok(_) | Err(_) => return Err(error!(NextWithoutFor)),
767            };
768            let var_name_val = self.stack.pop()?;
769            let step_val = self.stack.pop()?;
770            let to_val = self.stack.pop()?;
771            if let Val::String(var_name) = var_name_val {
772                if !next_name.is_empty() && var_name != next_name {
773                    continue;
774                }
775                let mut current = self.vars.fetch(&var_name);
776                current = Operation::sum(current, step_val.clone())?;
777                self.vars.store(&var_name, current.clone())?;
778                if let Ok(step) = f64::try_from(step_val.clone()) {
779                    let done = Val::Integer(-1)
780                        == if step < 0.0 {
781                            Operation::less(current, to_val.clone())?
782                        } else {
783                            Operation::less(to_val.clone(), current)?
784                        };
785                    if !done {
786                        self.stack.push(to_val)?;
787                        self.stack.push(step_val)?;
788                        self.stack.push(Val::String(var_name))?;
789                        self.stack.push(Val::Next(next))?;
790                        self.pc = next;
791                    }
792                    return Ok(());
793                }
794            }
795        }
796    }
797
798    fn r#on(&mut self) -> Result<()> {
799        let select = i16::try_from(self.stack.pop()?)?;
800        let len = i16::try_from(self.stack.pop()?)?;
801        if select < 0 || len < 0 {
802            return Err(error!(IllegalFunctionCall));
803        }
804        if select == 0 || select > len {
805            self.pc += len as usize;
806        } else {
807            self.pc += select as usize - 1;
808        }
809        Ok(())
810    }
811
812    fn r#print(&mut self) -> Result<Event> {
813        let item = self.stack.pop()?;
814        let val_str = match item {
815            Val::String(s) => s,
816            _ => format!("{} ", item).into(),
817        };
818        for ch in val_str.chars() {
819            match ch {
820                '\n' => self.print_col = 0,
821                _ => self.print_col += 1,
822            }
823        }
824        Ok(Event::Print(val_str.to_string()))
825    }
826
827    fn r#read(&mut self) -> Result<()> {
828        let val = self.program.read_data()?;
829        self.stack.push(val)
830    }
831
832    fn r#renum(&mut self) -> Result<Event> {
833        if self.pc < self.entry_address {
834            return Err(error!(IllegalDirect));
835        }
836        if !self.listing.indirect_errors.is_empty() {
837            return Ok(Event::Errors(Arc::clone(&self.listing.indirect_errors)));
838        }
839        let step = u16::try_from(self.stack.pop()?)?;
840        let old_start = u16::try_from(self.stack.pop()?)?;
841        let new_start = u16::try_from(self.stack.pop()?)?;
842        self.listing.renum(new_start, old_start, step)?;
843
844        self.state = State::Stopped;
845        Ok(self.r#end())
846    }
847
848    fn r#restore(&mut self, addr: Address) -> Result<()> {
849        self.program.restore_data(addr);
850        Ok(())
851    }
852
853    fn r#return(&mut self) -> Result<()> {
854        let mut ret_val: Option<Val> = None;
855        let mut first = true;
856        loop {
857            match self.stack.pop() {
858                Ok(Val::Return(addr)) => {
859                    if let Some(val) = ret_val {
860                        self.stack.push(val)?;
861                    }
862                    self.pc = addr;
863                    return Ok(());
864                }
865                Ok(val) => {
866                    if first
867                        && matches!(
868                            val,
869                            Val::String(..) | Val::Single(..) | Val::Double(..) | Val::Integer(..)
870                        )
871                    {
872                        ret_val = Some(val);
873                    }
874                    first = false;
875                    continue;
876                }
877                Err(_) => return Err(error!(ReturnWithoutGosub)),
878            }
879        }
880    }
881
882    fn r#save(&mut self) -> Result<Event> {
883        match self.stack.pop()? {
884            Val::String(s) => {
885                self.r#end();
886                if self.pc < self.entry_address {
887                    Err(error!(IllegalDirect))
888                } else {
889                    Ok(Event::Save(s.to_string()))
890                }
891            }
892            _ => Err(error!(TypeMismatch)),
893        }
894    }
895
896    fn r#swap(&mut self) -> Result<()> {
897        let (val1, val2) = self.stack.pop_2()?;
898        match val1 {
899            Val::Integer(_) if matches!(val2, Val::Integer(_)) => {}
900            Val::Single(_) if matches!(val2, Val::Single(_)) => {}
901            Val::Double(_) if matches!(val2, Val::Double(_)) => {}
902            Val::String(_) if matches!(val2, Val::String(_)) => {}
903            _ => {
904                self.stack.push(val2)?;
905                self.stack.push(val1)?;
906                return Err(error!(TypeMismatch));
907            }
908        }
909        self.stack.push(val1)?;
910        self.stack.push(val2)?;
911        Ok(())
912    }
913
914    fn r#troff(&mut self) {
915        self.tron = false;
916    }
917
918    fn r#tron(&mut self) {
919        self.tron = true;
920        self.tr = self.program.line_number_for(self.pc - 1);
921    }
922}
923
924type RuntimeStack = Stack<Val>;
925
926trait RuntimeStackTrait<T> {
927    fn pop_1_push<F: Fn(Val) -> Result<Val>>(&mut self, func: &F) -> Result<()>;
928    fn pop_2_push<F: Fn(Val, Val) -> Result<Val>>(&mut self, func: &F) -> Result<()>;
929    fn pop_vec(&mut self) -> Result<Stack<Val>>;
930}
931
932impl RuntimeStackTrait<Val> for RuntimeStack {
933    fn pop_1_push<F: Fn(Val) -> Result<Val>>(&mut self, func: &F) -> Result<()> {
934        let val = self.pop()?;
935        self.push(func(val)?)?;
936        Ok(())
937    }
938    fn pop_2_push<F: Fn(Val, Val) -> Result<Val>>(&mut self, func: &F) -> Result<()> {
939        let (val1, val2) = self.pop_2()?;
940        self.push(func(val1, val2)?)?;
941        Ok(())
942    }
943    fn pop_vec(&mut self) -> Result<Stack<Val>> {
944        if let Val::Integer(n) = self.pop()? {
945            self.pop_n(n as usize)
946        } else {
947            Err(error!(InternalError; "NO VECTOR ON STACK"))
948        }
949    }
950}