1pub mod native_fn;
2
3use crate::value::Value;
4use roan_error::frame::Frame;
5
6#[derive(Debug, Clone)]
8pub struct VM {
9 frames: Vec<Frame>,
11 stack: Vec<Value>,
13}
14
15impl VM {
16 pub fn new() -> Self {
17 Self {
18 frames: vec![],
19 stack: vec![],
20 }
21 }
22}
23
24impl VM {
25 pub fn push_frame(&mut self, frame: Frame) {
26 self.frames.push(frame);
27 }
28
29 pub fn pop_frame(&mut self) -> Option<Frame> {
30 self.frames.pop()
31 }
32
33 pub fn frame(&self) -> Option<&Frame> {
34 self.frames.last()
35 }
36
37 pub fn frames(&self) -> &[Frame] {
38 &self.frames
39 }
40}
41
42impl VM {
43 pub fn push(&mut self, value: Value) {
44 self.stack.push(value);
45 }
46
47 pub fn pop(&mut self) -> Option<Value> {
48 self.stack.pop()
49 }
50
51 pub fn peek(&self) -> Option<&Value> {
52 self.stack.last()
53 }
54
55 pub fn stack(&self) -> &[Value] {
56 &self.stack
57 }
58
59 pub fn stack_last(&self) -> Option<&Value> {
60 self.stack.last()
61 }
62}
63
64#[cfg(test)]
65mod tests {
66 use super::*;
67 use crate::value::Value;
68 use roan_error::TextSpan;
69
70 #[test]
71 fn test_vm() {
72 let mut vm = VM::new();
73 assert_eq!(vm.frames().len(), 0);
74 assert_eq!(vm.stack().len(), 0);
75
76 let frame = Frame::new(
77 "test".to_string(),
78 TextSpan::default(),
79 ".\\test.roan".to_string(),
80 );
81 vm.push_frame(frame.clone());
82 assert_eq!(vm.frames().len(), 1);
83
84 let value = Value::Int(42);
85 vm.push(value.clone());
86 assert_eq!(vm.stack().len(), 1);
87 assert_eq!(vm.peek(), Some(&value));
88
89 let popped = vm.pop().unwrap();
90 assert_eq!(popped, value);
91 assert_eq!(vm.stack().len(), 0);
92
93 let popped = vm.pop_frame().unwrap();
94 assert_eq!(vm.frames().len(), 0);
95 }
96}