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
16pub 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#[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 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 pub fn get_listing(&self) -> Listing {
228 self.listing.clone()
229 }
230
231 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 pub fn set_prompt(&mut self, prompt: &str) {
242 self.prompt = prompt.into();
243 }
244
245 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 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}