1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate serde_json;

use json::dump_state;

#[derive(Serialize, Debug, Clone, Copy)]
pub enum Value {
	Number{value: i32},
	Character{value: char}
}

#[derive(Serialize, Debug, Clone, Copy)]
pub enum Location {
	Cell(usize),
	Address(usize)
}

#[derive(Serialize, Debug, Clone, Copy)]
pub enum Operation {
	Inbox,
	Outbox,
	Add{cell: Location},
	Sub{cell: Location},
	CopyFrom{cell: Location},
	CopyTo{cell: Location},
	Label,
	Jump{next_operation: usize},
	JumpEqualsZero{next_operation: usize},
	JumpNegative{next_operation: usize},
	BumpPlus{cell: Location},
	BumpMinus{cell: Location},
}

pub mod json;
pub mod memory;
pub mod operators;
pub mod state;

pub struct CodeIterator<'a> {
	pub state: &'a mut state::InternalState,
	pub operations: Vec<Operation>,
	has_errored: bool,
	dump_file_path: &'a str
}

impl<'a> CodeIterator<'a> {
	pub fn new(_state: &'a mut state::InternalState, _operations: Vec<Operation>, dump_file_path: &'a str) -> Self {
		CodeIterator{state: _state, operations: _operations, has_errored: false, dump_file_path}
	}
}

impl<'a> Iterator for CodeIterator<'a> {
	type Item = Result<state::InternalState, String>;

	fn next(&mut self) -> Option<Self::Item> {
		let srcpath = self.dump_file_path;
		if self.has_errored {
			None
		}
		else if self.state.executed_instructions() > 10000 {
			self.has_errored = true;
			let result: Result<(), String> = Err(String::from("instructions limit reached"));
			dump_state(&self.state, srcpath, &result.err().unwrap());
			return None;
		}
		else if self.state.instruction_counter < self.operations.len() {
			let _operation = self.operations[self.state.instruction_counter];

			let result = self.state.apply(_operation);

			if result.is_err() {
				if let Operation::Inbox =  _operation {
					self.has_errored = false;
					dump_state(&self.state, srcpath, &result.err().unwrap());
					return None;
				}
				else {
					dump_state(&self.state, srcpath, &result.err().unwrap());
					self.has_errored = true;
				}
			}
			dump_state(&self.state, srcpath, &String::new());

			Some(Ok(self.state.clone()))
		}
		else {
			dump_state(&self.state, srcpath, &String::new());
			None
		}
	}
}