1pub mod tag;
6pub mod stack;
7pub mod trace;
8pub mod slot;
9
10use std::mem;
11
12use crate::common::{
13 number::build_number,
14 data::Data,
15 opcode::Opcode,
16 lambda::Captured,
17 closure::Closure,
18 span::Span,
19};
20
21use crate::vm::{
22 trace::Trace,
23 slot::Suspend,
24 stack::Stack,
25};
26
27#[derive(Debug)]
33pub struct VM {
34 pub closure: Closure,
35 pub stack: Stack,
36 pub ip: usize,
37}
38
39impl VM {
45 pub fn init(closure: Closure) -> VM {
48 let mut vm = VM {
49 closure,
50 stack: Stack::init(),
51 ip: 0,
52 };
53 vm.stack.declare(vm.closure.lambda.decls);
54 vm
55 }
56
57 #[inline]
59 pub fn next(&mut self) { self.ip += 1; }
60 #[inline]
62 pub fn done(&mut self) -> Result<(), Trace> { self.next(); Ok(()) }
63 #[inline]
65 pub fn peek_byte(&mut self) -> u8 { self.closure.lambda.code[self.ip] }
66 #[inline]
68 pub fn next_byte(&mut self) -> u8 { self.next(); self.peek_byte() }
69
70 #[inline]
72 pub fn is_terminated(&mut self) -> bool {
73 self.ip >= self.closure.lambda.code.len()
74 }
75
76 #[inline]
79 pub fn next_number(&mut self) -> usize {
80 self.next();
81 let remaining = &self.closure.lambda.code[self.ip..];
82 let (index, eaten) = build_number(remaining);
83 self.ip += eaten - 1; index
85 }
86
87 #[inline]
88 pub fn current_span(&self) -> Span {
89 self.closure.lambda.index_span(self.ip)
90 }
91
92 pub fn step(&mut self) -> Result<(), Trace> {
98 let opcode = Opcode::from_byte(self.peek_byte());
99
100 match opcode {
101 Opcode::Con => self.con(),
102 Opcode::NotInit => self.not_init(),
103 Opcode::Del => self.del(),
104 Opcode::FFICall => self.ffi_call(),
105 Opcode::Copy => self.copy_val(),
106 Opcode::Capture => self.capture(),
107 Opcode::Save => self.save(),
108 Opcode::SaveCap => self.save_cap(),
109 Opcode::Load => self.load(),
110 Opcode::LoadCap => self.load_cap(),
111 Opcode::Call => self.call(),
112 Opcode::Return => self.return_val(),
113 Opcode::Closure => self.closure(),
114 Opcode::Print => self.print(),
115 Opcode::Label => self.label(),
116 Opcode::Tuple => self.tuple(),
117 Opcode::UnData => self.un_data(),
118 Opcode::UnLabel => self.un_label(),
119 Opcode::UnTuple => self.un_tuple(),
120 }
121 }
122
123 pub fn unwind(&mut self) {
124 let suspend = self.stack.pop_frame(); self.ip = suspend.ip;
127 self.closure = suspend.closure;
128
129 self.stack.push_not_init();
131 }
132
133 pub fn run(&mut self) -> Result<(), Trace> {
139 let mut result = Ok(());
141
142 while !self.is_terminated() {
143 result = self.step();
146 if result.is_err() { break; }
147 }
149 if let Err(mut trace) = result {
153 while self.stack.unwind_frame() {
154 self.unwind();
155 self.ip -= 1;
156 trace.add_context(self.current_span());
157 }
158
159 result = Err(trace);
160 };
161
162 result
163 }
164
165 #[inline]
175 pub fn con(&mut self) -> Result<(), Trace> {
176 let index = self.next_number();
178
179 self.stack.push_data(self.closure.lambda.constants[index].clone());
180 self.done()
181 }
182
183 #[inline]
184 pub fn not_init(&mut self) -> Result<(), Trace> {
185 self.stack.push_not_init();
186 self.done()
187 }
188
189 #[inline]
192 pub fn capture(&mut self) -> Result<(), Trace> {
193 let index = self.next_number();
194 self.stack.heapify(index); self.done()
196 }
197
198 #[inline]
200 pub fn save(&mut self) -> Result<(), Trace> {
201 let index = self.next_number();
202 self.stack.set_local(index);
203 self.done()
204 }
205
206 #[inline]
208 pub fn save_cap(&mut self) -> Result<(), Trace> {
209 let index = self.next_number();
210 let data = self.stack.pop_data();
211 mem::drop(self.closure.captures[index].replace(data));
212 self.done()
213 }
214
215 #[inline]
217 pub fn load(&mut self) -> Result<(), Trace> {
218 let index = self.next_number();
219 let mut data = self.stack.local_data(index);
220
221 if let Data::Heaped(d) = data { data = d.borrow().to_owned() };
222 if let Data::NotInit = data {
223 return Err(Trace::error(
224 "Reference",
225 "This local variable was referenced before assignment",
226 vec![self.current_span()],
227 ));
228 };
229
230 self.stack.push_data(data);
231 self.done()
232 }
233
234 #[inline]
236 pub fn load_cap(&mut self) -> Result<(), Trace> {
237 let index = self.next_number();
238 let data = self.closure.captures[index].borrow().to_owned();
239
240 if let Data::NotInit = data {
241 return Err(Trace::error(
242 "Reference",
243 "This captured variable was referenced before assignment",
244 vec![self.current_span()],
245 ));
246 };
247
248 self.stack.push_data(data);
249 self.done()
250 }
251
252 #[inline]
254 pub fn del(&mut self) -> Result<(), Trace> {
255 mem::drop(self.stack.pop_data());
256 self.done()
257 }
258
259 #[inline]
262 pub fn copy_val(&mut self) -> Result<(), Trace> {
263 let data = self.stack.pop_data();
264 self.stack.push_data(data.clone());
265 self.stack.push_data(data);
266 self.done()
267 }
268
269 #[inline]
270 pub fn print(&mut self) -> Result<(), Trace> {
271 let data = self.stack.pop_data();
272 println!("{}", data);
273 self.stack.push_data(data);
274 self.done()
275 }
276
277 #[inline]
278 pub fn label(&mut self) -> Result<(), Trace> {
279 let kind = match self.stack.pop_data() {
280 Data::Kind(n) => n,
281 _ => unreachable!(),
282 };
283 let data = self.stack.pop_data();
284 self.stack.push_data(Data::Label(Box::new(kind), Box::new(data)));
285 self.done()
286 }
287
288 #[inline]
289 pub fn tuple(&mut self) -> Result<(), Trace> {
290 let index = self.next_number();
291 let mut items = vec![];
292 for _ in 0..index {
293 items.push(self.stack.pop_data())
294 }
295
296 items.reverse();
297 self.stack.push_data(Data::Tuple(items));
298 self.done()
299 }
300
301 fn un_data(&mut self) -> Result<(), Trace> {
302 let expected = self.stack.pop_data();
303 let data = self.stack.pop_data();
304
305 if data != expected {
306 return Err(Trace::error(
307 "Pattern Matching",
308 &format!("The data '{}' does not match the expected data '{}'", data, expected),
309 vec![self.current_span()],
310 ));
311 }
312
313 self.done()
314 }
315
316 fn un_label(&mut self) -> Result<(), Trace> {
317 let kind = match self.stack.pop_data() {
318 Data::Kind(n) => n,
319 _ => unreachable!(),
320 };
321
322 let d = match self.stack.pop_data() {
323 Data::Label(n, d) if *n == kind => d,
324 other => return Err(Trace::error(
325 "Pattern Matching",
326 &format!("The data '{}' does not match the Label '{}'", other, kind),
327 vec![self.current_span()],
328 )),
329 };
330
331 self.stack.push_data(*d);
332 self.done()
333 }
334
335 fn un_tuple(&mut self) -> Result<(), Trace> {
336 let index = self.next_number();
337 let t = match self.stack.pop_data() {
338 Data::Tuple(t) => t,
339 other => return Err(Trace::error(
340 "Pattern Matching",
341 &format!("The data '{}' is not a tuple", other),
342 vec![self.current_span()],
343 )),
344 };
345
346 let length = t.len();
347 if index >= length {
348 return Err(Trace::error(
349 "Indexing",
350 &format!(
351 "The tuple '{}' is of length {}, so the index {} is out-of-bounds",
352 Data::Tuple(t), length, index
353 ),
354 vec![self.current_span()],
355 ));
356 }
357
358 let data = t[index].clone();
359 self.stack.push_data(Data::Tuple(t));
360 self.stack.push_data(data);
361 self.done()
362 }
363
364 pub fn call(&mut self) -> Result<(), Trace> {
366 let fun = match self.stack.pop_data() {
368 Data::Closure(c) => *c,
369 o => return Err(Trace::error(
370 "Call",
371 &format!("The data '{}' is not a function and can not be called", o),
372 vec![self.current_span()],
373 )),
374 };
375 let arg = self.stack.pop_data();
376
377 self.next();
380 let tail_call = !self.is_terminated()
381 && Opcode::Return
382 == Opcode::from_byte(self.peek_byte());
383
384 if tail_call {
387 let locals = self.next_number();
388 for _ in 0..locals { self.del()?; }
389 }
390
391 let old_closure = mem::replace(&mut self.closure, fun);
393 let old_ip = mem::replace(&mut self.ip, 0);
394 let suspend = Suspend {
395 ip: old_ip,
396 closure: old_closure,
397 };
398
399 if !tail_call {
403 self.stack.push_frame(suspend);
404 }
405
406 self.stack.declare(self.closure.lambda.decls);
409 self.stack.push_data(arg);
410
411 Ok(())
414 }
415
416 pub fn return_val(&mut self) -> Result<(), Trace> {
422 let val = self.stack.pop_data();
424
425 let locals = self.next_number();
427 for _ in 0..locals { self.del()?; }
428
429 let suspend = self.stack.pop_frame(); self.ip = suspend.ip;
432 self.closure = suspend.closure;
433
434 self.stack.push_data(val); Ok(())
437 }
438
439 pub fn closure(&mut self) -> Result<(), Trace> {
440 let index = self.next_number();
441
442 let lambda = match self.closure.lambda.constants[index].clone() {
443 Data::Lambda(lambda) => lambda,
444 _ => unreachable!("Expected a lambda to be wrapped with a closure"),
445 };
446
447 let mut closure = Closure::wrap(lambda);
448
449 for captured in closure.lambda.captures.iter() {
450 let reference = match captured {
451 Captured::Local(index) => {
452 match self.stack.local_data(*index) {
453 Data::Heaped(h) => h,
454 _ => unreachable!("Expected data to be on the heap"),
455 }
456 },
457 Captured::Nonlocal(upvalue) => self.closure.captures[*upvalue].clone(),
458 };
459 closure.captures.push(reference)
460 }
461
462 self.stack.push_data(Data::Closure(Box::new(closure)));
463 self.done()
464 }
465
466 pub fn ffi_call(&mut self) -> Result<(), Trace> {
467 let index = self.next_number();
468 let ffi_function = &self.closure.lambda.ffi[index];
469
470 let argument = self.stack.pop_data();
471 let returned = match ffi_function.call(argument) {
472 Ok(d) => d,
473 Err(e) => return Err(Trace::error(
474 "FFI Call", &e, vec![self.current_span()],
475 )),
476 };
477
478 self.stack.push_data(returned);
479 self.done()
480 }
481}
482
483#[cfg(test)]
484mod test {
485 use super::*;
486 use crate::compiler::{
487 lex::lex,
488 parse::parse,
489 desugar::desugar,
490 hoist::hoist,
491 gen::gen,
492 };
493 use crate::common::source::Source;
494
495 fn inspect(source: &str) -> VM {
496 let lambda = lex(Source::source(source))
497 .and_then(parse)
498 .and_then(desugar)
499 .and_then(hoist)
500 .and_then(gen)
501 .map_err(|e| println!("{}", e))
502 .unwrap();
503
504 let mut vm = VM::init(Closure::wrap(lambda));
506
507 match vm.run() {
508 Ok(()) => vm,
509 Err(e) => {
510 println!("{}", e);
511 panic!();
512 },
513 }
514 }
515
516 #[test]
517 fn init_run() {
518 inspect("x = 0.0");
519 }
520
521 #[test]
522 fn block_expression() {
523 inspect("x = false; boop = true; heck = { x = boop; x }; heck");
524 }
525
526 #[test]
527 fn functions() {
528 let mut vm = inspect("iden = x -> x; y = true; iden ({ y = false; iden iden } (iden y))");
529 let identity = vm.stack.pop_data();
530 assert_eq!(identity, Data::Boolean(true));
531 }
532
533 #[test]
534 fn fun_scope() {
535 let mut vm = inspect("one = 1.0\npi = 3.14\ne = 2.72\n\nx = w -> pi\nx 37.6");
537 let pi = vm.stack.pop_data();
538 assert_eq!(pi, Data::Real(3.14));
539 }
540
541 #[test]
542 fn mutate_capture() {
543 inspect("odd = (); even = x -> odd; odd = 1.0; even (); odd");
544 }
545
546 #[test]
547 fn mutate_capture_fn() {
548 inspect("\
549 pi = 3.14\n\
550 printpi = x -> println pi\n\
551 \n\
552 redef = ()\n\
553 redef = w -> {\n \
554 w (printpi ())\n\
555 }\n\
556 \n\
557 redef printpi\n\
558 ");
559 }
560
561 #[test]
562 fn hoist_later() {
563 inspect("\
564 w = 0.5
565 later = n -> thing 10.0 - w\n\
566 thing = x -> x + 20.0\n\
567 -- later 5.0\n\
568 ");
569 }
570
571 }