Skip to content

Commit 8c9d50e

Browse files
committed
Refactor VM
- Move some functions into their own files - Move VM into it's own module
1 parent e9dafb8 commit 8c9d50e

File tree

7 files changed

+290
-267
lines changed

7 files changed

+290
-267
lines changed

zenlang/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,5 @@ pub mod tokenizer;
1212
pub mod unescape;
1313
pub mod value;
1414
pub mod vm;
15-
pub mod vmcall;
1615

1716
extern crate alloc;

zenlang/src/vm/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
pub mod vm;
2+
pub mod vm_aiafs;
3+
pub mod vm_compute;
4+
pub mod vm_opcode;
5+
pub mod vmcall;
6+
pub use vm::*;

zenlang/src/vm/vm.rs

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
use crate::module::Module;
2+
use crate::platform::Platform;
3+
use crate::scope::Scope;
4+
use crate::strong_u64::*;
5+
use crate::value::*;
6+
use alloc::boxed::*;
7+
use alloc::string::*;
8+
use alloc::vec::*;
9+
10+
static MAX_STACK_SIZE: usize = 1000;
11+
12+
pub struct VM<'a> {
13+
pub modules: Vec<&'a mut Module>,
14+
pub pc: u64,
15+
pub stack: Vec<Value>,
16+
pub call_stack: Vec<u64>,
17+
pub scopes: Vec<Scope>,
18+
pub error: String,
19+
pub ret: Value,
20+
pub platform: Option<Box<dyn Platform>>,
21+
pub(crate) bfas_stack_start: i64,
22+
pub(crate) bfas_stack_end: i64,
23+
}
24+
25+
impl<'a> VM<'a> {
26+
pub fn new() -> VM<'a> {
27+
return VM {
28+
modules: Vec::new(),
29+
pc: 0,
30+
stack: Vec::new(),
31+
call_stack: Vec::new(),
32+
scopes: Vec::new(),
33+
error: String::new(),
34+
ret: Value::Null(),
35+
platform: None,
36+
bfas_stack_start: 0,
37+
bfas_stack_end: 0,
38+
};
39+
}
40+
41+
pub fn load_module(&mut self, module: &'a mut Module) {
42+
self.modules.push(module);
43+
}
44+
45+
pub fn set_entry_function(&mut self, entry_fn_name: &str) -> Result<(), &'static str> {
46+
for i in 0..self.modules.len() {
47+
let module = &self.modules[i];
48+
for function in module.functions.iter() {
49+
if function.name == entry_fn_name {
50+
self.pc.set_low(function.addr as u32);
51+
self.pc.set_high(i as u32);
52+
self.add_scope();
53+
return Ok(());
54+
}
55+
}
56+
}
57+
return Err("cannot find entry function");
58+
}
59+
60+
pub(crate) fn check_stack_overflow(&mut self) {
61+
if self.call_stack.len() >= MAX_STACK_SIZE {
62+
self.error = "call stack overflow".into();
63+
}
64+
if self.stack.len() >= MAX_STACK_SIZE {
65+
self.error = "call stack overflow".into();
66+
}
67+
}
68+
69+
pub(crate) fn add_scope(&mut self) {
70+
self.scopes.push(Scope::new());
71+
}
72+
73+
pub(crate) fn remove_scope(&mut self) {
74+
self.scopes.pop();
75+
}
76+
77+
pub fn step(&mut self) -> bool {
78+
if !self.error.is_empty() {
79+
return false;
80+
}
81+
82+
let module_index = self.pc.get_high() as usize;
83+
let opcode_index = self.pc.get_low();
84+
if module_index >= self.modules.len() {
85+
return false;
86+
}
87+
88+
let opcodes = core::mem::take(&mut self.modules[module_index].opcodes);
89+
if opcode_index >= opcodes.len() as u32 {
90+
return false;
91+
}
92+
93+
let opcode = &opcodes[opcode_index as usize];
94+
95+
self.execute_opcode(opcode);
96+
97+
self.modules[module_index].opcodes = opcodes;
98+
99+
self.pc.add_low(1);
100+
101+
return true;
102+
}
103+
}

zenlang/src/vm/vm_aiafs.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
use crate::value::*;
2+
use crate::vm::*;
3+
use alloc::format;
4+
use alloc::vec::*;
5+
6+
impl<'a> VM<'a> {
7+
pub(crate) fn aiafs(&mut self, value: Value, set_to: Value, mut indexes: Vec<Value>) -> Value {
8+
match value {
9+
Value::Array(mut array) => {
10+
let index = indexes[0].clone();
11+
if let Value::Number(index) = index {
12+
let usize_index = index as usize;
13+
if usize_index >= array.len() {
14+
self.error = format!(
15+
"aiafs failed: index ({}) is larger or equal to array length ({})",
16+
usize_index,
17+
array.len()
18+
);
19+
return Value::Null();
20+
}
21+
22+
if indexes.len() == 1 {
23+
array[usize_index] = set_to;
24+
return Value::Array(array);
25+
} else {
26+
indexes.remove(0);
27+
if let Value::Array(inner) = &array[usize_index] {
28+
array[usize_index] =
29+
self.aiafs(Value::Array(inner.clone()), set_to, indexes);
30+
return Value::Array(array);
31+
}
32+
}
33+
}
34+
}
35+
Value::Dictionary(mut dict) => {
36+
let index = indexes[0].clone();
37+
if let Value::String(index) = index {
38+
for element in dict.iter_mut() {
39+
if element.0 != index {
40+
continue;
41+
}
42+
43+
if indexes.len() == 1 {
44+
(*element).1 = set_to;
45+
return Value::Dictionary(dict);
46+
} else {
47+
indexes.remove(0);
48+
if let Value::Dictionary(inner) = &element.1 {
49+
(*element).1 =
50+
self.aiafs(Value::Dictionary(inner.clone()), set_to, indexes);
51+
return Value::Dictionary(dict);
52+
}
53+
}
54+
}
55+
}
56+
}
57+
_ => {}
58+
}
59+
self.error = format!("aiafs failed: invalid operand types");
60+
return Value::Null();
61+
}
62+
}

zenlang/src/vm/vm_compute.rs

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
use crate::ast::binop::*;
2+
use crate::value::*;
3+
use crate::vm::*;
4+
5+
impl<'a> VM<'a> {
6+
pub(crate) fn compute_values(&mut self, left: Value, right: Value, op: AstBinopOp) -> Value {
7+
match op {
8+
AstBinopOp::PLUS => {
9+
if let Value::Number(left_num) = left {
10+
if let Value::Number(right_num) = right {
11+
return Value::Number(left_num + right_num);
12+
}
13+
}
14+
}
15+
AstBinopOp::MINUS => {
16+
if let Value::Number(left_num) = left {
17+
if let Value::Number(right_num) = right {
18+
return Value::Number(left_num - right_num);
19+
}
20+
}
21+
}
22+
AstBinopOp::MUL => {
23+
if let Value::Number(left_num) = left {
24+
if let Value::Number(right_num) = right {
25+
return Value::Number(left_num * right_num);
26+
}
27+
}
28+
}
29+
AstBinopOp::DIV => {
30+
if let Value::Number(left_num) = left {
31+
if let Value::Number(right_num) = right {
32+
if right_num == 0.0 {
33+
self.error = "division by 0".into();
34+
return Value::Null();
35+
}
36+
return Value::Number(left_num / right_num);
37+
}
38+
}
39+
}
40+
AstBinopOp::BITSHR => {
41+
if let Value::Number(left_num) = left {
42+
if let Value::Number(right_num) = right {
43+
return Value::Number(((left_num as i64) >> (right_num as i64)) as f64);
44+
}
45+
}
46+
}
47+
AstBinopOp::BITSHL => {
48+
if let Value::Number(left_num) = left {
49+
if let Value::Number(right_num) = right {
50+
return Value::Number(((left_num as i64) << (right_num as i64)) as f64);
51+
}
52+
}
53+
}
54+
AstBinopOp::BITAND => {
55+
if let Value::Number(left_num) = left {
56+
if let Value::Number(right_num) = right {
57+
return Value::Number(((left_num as i64) & (right_num as i64)) as f64);
58+
}
59+
}
60+
if let Value::Boolean(left) = left {
61+
if let Value::Boolean(right) = right {
62+
return Value::Number((left && right) as i64 as f64);
63+
}
64+
}
65+
}
66+
AstBinopOp::BITOR => {
67+
if let Value::Number(left_num) = left {
68+
if let Value::Number(right_num) = right {
69+
return Value::Number(((left_num as i64) | (right_num as i64)) as f64);
70+
}
71+
}
72+
if let Value::Boolean(left) = left {
73+
if let Value::Boolean(right) = right {
74+
return Value::Number((left || right) as i64 as f64);
75+
}
76+
}
77+
}
78+
AstBinopOp::EQ => {
79+
return Value::Boolean(left.equal(&right));
80+
}
81+
AstBinopOp::NEQ => {
82+
return Value::Boolean(!left.equal(&right));
83+
}
84+
AstBinopOp::LT => {
85+
return Value::Boolean(left.lt(&right));
86+
}
87+
AstBinopOp::GT => {
88+
return Value::Boolean(left.gt(&right));
89+
}
90+
AstBinopOp::LE => {
91+
return Value::Boolean(left.le(&right));
92+
}
93+
AstBinopOp::GE => {
94+
return Value::Boolean(left.ge(&right));
95+
}
96+
}
97+
self.error = "unmatched left and right value types".into();
98+
return Value::Null();
99+
}
100+
101+
pub(crate) fn compute_stack_values(&mut self, op: AstBinopOp) -> Value {
102+
let mut left = Value::Null();
103+
let mut right = Value::Null();
104+
105+
if let Some(value) = self.stack.pop() {
106+
right = value;
107+
}
108+
if let Some(value) = self.stack.pop() {
109+
left = value;
110+
}
111+
112+
return self.compute_values(left, right, op);
113+
}
114+
}

0 commit comments

Comments
 (0)