multitask/
vm.rs

1extern crate hibitset;
2extern crate rtforth;
3
4use self::hibitset::BitSet;
5use rtforth::core::{Control, Core, ForwardReferences, Stack, State, Wordlist};
6use rtforth::env::Environment;
7use rtforth::exception::Exception;
8use rtforth::facility::Facility;
9use rtforth::file_access::FileAccess;
10use rtforth::float::Float;
11use rtforth::loader::{HasLoader, Source};
12use rtforth::memory::DataSpace;
13use rtforth::output::Output;
14use rtforth::tools::Tools;
15use rtforth::units::Units;
16use rtforth::NUM_TASKS;
17use std::fs::File;
18use std::time::Instant;
19
20const BUFFER_SIZE: usize = 0x400;
21const LABEL_COUNT: u32 = 1000;
22
23/// Task
24///
25/// Each task has its own input buffer but shares the
26/// dictionary and output buffer owned by virtual machine.
27pub struct Task {
28    awake: bool,
29    state: State,
30    s_stk: Stack<isize>,
31    r_stk: Stack<isize>,
32    c_stk: Stack<Control>,
33    f_stk: Stack<f64>,
34    inbuf: Option<String>,
35    files: Vec<Option<File>>,
36    sources: Vec<Option<Source>>,
37    lines: Vec<Option<String>>,
38}
39
40impl Task {
41    /// Create a task without input buffer.
42    pub fn new_background() -> Task {
43        Task {
44            awake: false,
45            state: State::new(),
46            s_stk: Stack::new(0x12345678),
47            r_stk: Stack::new(0x12345678),
48            c_stk: Stack::new(Control::Canary),
49            f_stk: Stack::new(1.234567890),
50            inbuf: None,
51            files: Vec::new(),
52            sources: Vec::new(),
53            lines: Vec::new(),
54        }
55    }
56
57    /// Create a task with input buffer.
58    pub fn new_terminal() -> Task {
59        let mut task = Task::new_background();
60        task.inbuf = Some(String::with_capacity(BUFFER_SIZE));
61        task
62    }
63}
64
65/// Virtual machine
66pub struct VM {
67    current_task: usize,
68    tasks: [Task; NUM_TASKS],
69    last_error: Option<Exception>,
70    handler: usize,
71    wordlist: Wordlist<VM>,
72    data_space: DataSpace,
73    tkn: Option<String>,
74    outbuf: Option<String>,
75    hldbuf: String,
76    references: ForwardReferences,
77    now: Instant,
78    forward_bitset: BitSet,
79    resolved_bitset: BitSet,
80    labels: Vec<usize>,
81}
82
83impl VM {
84    /// Create a VM with data space size specified by `data_pages`.
85    pub fn new(data_pages: usize) -> VM {
86        let mut labels = Vec::with_capacity(LABEL_COUNT as _);
87        labels.resize(LABEL_COUNT as _, 0);
88        let mut vm = VM {
89            current_task: 0,
90            tasks: [
91                // Only operator task has its own input buffer.
92                Task::new_terminal(),
93                Task::new_background(),
94                Task::new_background(),
95                Task::new_background(),
96                Task::new_background(),
97            ],
98            last_error: None,
99            handler: 0,
100            wordlist: Wordlist::with_capacity(1000),
101            data_space: DataSpace::new(data_pages),
102            tkn: Some(String::with_capacity(64)),
103            outbuf: Some(String::with_capacity(128)),
104            hldbuf: String::with_capacity(128),
105            references: ForwardReferences::new(),
106            now: Instant::now(),
107            forward_bitset: BitSet::with_capacity(LABEL_COUNT),
108            resolved_bitset: BitSet::with_capacity(LABEL_COUNT),
109            labels,
110        };
111        vm.add_core();
112        vm.add_output();
113        vm.add_tools();
114        vm.add_environment();
115        vm.add_facility();
116        vm.add_float();
117        vm.add_units();
118        vm.add_file_access();
119        vm.add_loader();
120
121        vm.load_core_fth();
122
123        vm
124    }
125}
126
127impl Core for VM {
128    fn last_error(&self) -> Option<Exception> {
129        self.last_error
130    }
131    fn set_error(&mut self, e: Option<Exception>) {
132        self.last_error = e;
133    }
134    fn handler(&self) -> usize {
135        self.handler
136    }
137    fn set_handler(&mut self, h: usize) {
138        self.handler = h;
139    }
140    fn data_space(&mut self) -> &mut DataSpace {
141        &mut self.data_space
142    }
143    fn data_space_const(&self) -> &DataSpace {
144        &self.data_space
145    }
146    fn hold_buffer(&mut self) -> &mut String {
147        &mut self.hldbuf
148    }
149    fn output_buffer(&mut self) -> &mut Option<String> {
150        &mut self.outbuf
151    }
152    fn set_output_buffer(&mut self, buffer: String) {
153        self.outbuf = Some(buffer);
154    }
155    fn source_id(&self) -> isize {
156        self.tasks[self.current_task].state.source_id
157    }
158    fn input_buffer(&mut self) -> &mut Option<String> {
159        let source_id = self.source_id();
160        if source_id > 0 {
161            &mut self.lines_mut()[source_id as usize - 1]
162        } else {
163            &mut self.tasks[self.current_task].inbuf
164        }
165    }
166    fn set_input_buffer(&mut self, buffer: String) {
167        *self.input_buffer() = Some(buffer);
168    }
169    fn files(&self) -> &Vec<Option<File>> {
170        &self.tasks[self.current_task].files
171    }
172    fn files_mut(&mut self) -> &mut Vec<Option<File>> {
173        &mut self.tasks[self.current_task].files
174    }
175    fn sources(&self) -> &Vec<Option<Source>> {
176        &self.tasks[self.current_task].sources
177    }
178    fn sources_mut(&mut self) -> &mut Vec<Option<Source>> {
179        &mut self.tasks[self.current_task].sources
180    }
181    fn lines(&self) -> &Vec<Option<String>> {
182        &self.tasks[self.current_task].lines
183    }
184    fn lines_mut(&mut self) -> &mut Vec<Option<String>> {
185        &mut self.tasks[self.current_task].lines
186    }
187    fn last_token(&mut self) -> &mut Option<String> {
188        &mut self.tkn
189    }
190    fn set_last_token(&mut self, buffer: String) {
191        self.tkn = Some(buffer);
192    }
193    fn s_stack(&mut self) -> &mut Stack<isize> {
194        &mut self.tasks[self.current_task].s_stk
195    }
196    fn r_stack(&mut self) -> &mut Stack<isize> {
197        &mut self.tasks[self.current_task].r_stk
198    }
199    fn c_stack(&mut self) -> &mut Stack<Control> {
200        &mut self.tasks[self.current_task].c_stk
201    }
202    fn f_stack(&mut self) -> &mut Stack<f64> {
203        &mut self.tasks[self.current_task].f_stk
204    }
205    fn wordlist_mut(&mut self) -> &mut Wordlist<Self> {
206        &mut self.wordlist
207    }
208    fn wordlist(&self) -> &Wordlist<Self> {
209        &self.wordlist
210    }
211    fn state(&mut self) -> &mut State {
212        &mut self.tasks[self.current_task].state
213    }
214    fn references(&mut self) -> &mut ForwardReferences {
215        &mut self.references
216    }
217    fn system_time_ns(&self) -> u64 {
218        let elapsed = self.now.elapsed();
219        elapsed.as_nanos() as _
220    }
221    fn current_task(&self) -> usize {
222        self.current_task
223    }
224    fn set_current_task(&mut self, i: usize) {
225        if i < NUM_TASKS {
226            self.current_task = i;
227        } else {
228            // Do nothing.
229        }
230    }
231    fn awake(&self, i: usize) -> bool {
232        if i < NUM_TASKS {
233            self.tasks[i].awake
234        } else {
235            false
236        }
237    }
238    fn set_awake(&mut self, i: usize, v: bool) {
239        if i < NUM_TASKS {
240            self.tasks[i].awake = v;
241        } else {
242            // Do nothing.
243        }
244    }
245    fn forward_bitset(&self) -> &BitSet {
246        &self.forward_bitset
247    }
248    fn forward_bitset_mut(&mut self) -> &mut BitSet {
249        &mut self.forward_bitset
250    }
251    fn resolved_bitset(&self) -> &BitSet {
252        &self.resolved_bitset
253    }
254    fn resolved_bitset_mut(&mut self) -> &mut BitSet {
255        &mut self.resolved_bitset
256    }
257    fn labels(&self) -> &Vec<usize> {
258        &self.labels
259    }
260    fn labels_mut(&mut self) -> &mut Vec<usize> {
261        &mut self.labels
262    }
263}
264
265impl Environment for VM {}
266impl Facility for VM {}
267impl Float for VM {}
268impl Units for VM {}
269impl FileAccess for VM {}
270impl HasLoader for VM {}
271impl Output for VM {}
272impl Tools for VM {}