aboutsummaryrefslogtreecommitdiffstats
path: root/src/vm.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/vm.rs')
-rw-r--r--src/vm.rs271
1 files changed, 7 insertions, 264 deletions
diff --git a/src/vm.rs b/src/vm.rs
index 6ff2cf3..849aaa1 100644
--- a/src/vm.rs
+++ b/src/vm.rs
@@ -1,16 +1,15 @@
-use owo_colors::OwoColorize;
-use std::collections::HashMap;
+use std::cell::RefCell;
use std::collections::hash_map::Entry;
+use std::collections::HashMap;
use std::fmt::Debug;
-use std::path::{Path, PathBuf};
use std::rc::Rc;
-use std::cell::RefCell;
-pub use crate::compiler::Type;
+use owo_colors::OwoColorize;
-use crate::compiler::RustFunction;
+use crate::{Blob, Block, Op, Prog, UpValue, Value};
use crate::error::{Error, ErrorKind};
-use crate::compiler::{Prog, Blob};
+use crate::RustFunction;
+pub use crate::Type;
macro_rules! error {
( $thing:expr, $kind:expr) => {
@@ -21,262 +20,6 @@ macro_rules! error {
};
}
-#[derive(Clone)]
-pub enum Value {
- Blob(usize),
- BlobInstance(usize, Rc<RefCell<Vec<Value>>>),
- Float(f64),
- Int(i64),
- Bool(bool),
- String(Rc<String>),
- Function(Vec<Rc<RefCell<UpValue>>>, Rc<RefCell<Block>>),
- ExternFunction(usize),
- Unkown,
- Nil,
-}
-
-#[derive(Clone, Debug)]
-pub struct UpValue {
- slot: usize,
- value: Value,
-}
-
-impl UpValue {
- fn new(value: usize) -> Self {
- Self {
- slot: value,
- value: Value::Nil,
- }
- }
-
- fn get(&self, stack: &[Value]) -> Value {
- if self.is_closed() {
- self.value.clone()
- } else {
- stack[self.slot].clone()
- }
- }
-
- fn set(&mut self, stack: &mut [Value], value: Value) {
- if self.is_closed() {
- self.value = value;
- } else {
- stack[self.slot] = value;
- }
- }
-
-
- fn is_closed(&self) -> bool {
- self.slot == 0
- }
-
- fn close(&mut self, value: Value) {
- self.slot = 0;
- self.value = value;
- }
-}
-
-impl Debug for Value {
- fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- match self {
- Value::Blob(i) => write!(fmt, "(blob {})", i),
- Value::BlobInstance(i, v) => write!(fmt, "(inst {} {:?})", i, v),
- Value::Float(f) => write!(fmt, "(float {})", f),
- Value::Int(i) => write!(fmt, "(int {})", i),
- Value::Bool(b) => write!(fmt, "(bool {})", b),
- Value::String(s) => write!(fmt, "(string \"{}\")", s),
- Value::Function(_, block) => write!(fmt, "(fn {}: {:?})", block.borrow().name, block.borrow().ty),
- Value::ExternFunction(slot) => write!(fmt, "(extern fn {})", slot),
- Value::Unkown => write!(fmt, "(unkown)"),
- Value::Nil => write!(fmt, "(nil)"),
- }
- }
-}
-
-impl Value {
- fn identity(self) -> Self {
- match self {
- Value::Float(_) => Value::Float(1.0),
- Value::Int(_) => Value::Int(1),
- Value::Bool(_) => Value::Bool(true),
- a => a,
- }
- }
-
- fn as_type(&self) -> Type {
- match self {
- Value::BlobInstance(i, _) => Type::BlobInstance(*i),
- Value::Blob(i) => Type::Blob(*i),
- Value::Float(_) => Type::Float,
- Value::Int(_) => Type::Int,
- Value::Bool(_) => Type::Bool,
- Value::String(_) => Type::String,
- Value::Function(_, block) => block.borrow().ty.clone(),
- Value::ExternFunction(_) => Type::Void, //TODO
- Value::Unkown => Type::UnknownType,
- Value::Nil => Type::Void,
- }
- }
-}
-
-#[derive(Debug, Clone)]
-pub enum Op {
- Illegal,
-
- Pop,
- PopUpvalue,
- Constant(Value),
-
- Get(String),
- Set(String),
-
- Add,
- Sub,
- Mul,
- Div,
- Neg,
-
- And,
- Or,
- Not,
-
- Jmp(usize),
- JmpFalse(usize),
-
- Equal, // ==
- Less, // <
- Greater, // >
-
- Assert,
- Unreachable,
-
- ReadLocal(usize),
- AssignLocal(usize),
-
- ReadUpvalue(usize),
- AssignUpvalue(usize),
-
- Define(Type),
-
- Call(usize),
-
- Print,
- Return,
-}
-
-#[derive(Debug)]
-pub struct Block {
- pub ty: Type,
- pub ups: Vec<(usize, bool, Type)>,
-
- pub name: String,
- pub file: PathBuf,
- pub ops: Vec<Op>,
- pub last_line_offset: usize,
- pub line_offsets: HashMap<usize, usize>,
- pub line: usize,
-}
-
-impl Block {
- pub fn new(name: &str, file: &Path, line: usize) -> Self {
- Self {
- ty: Type::Void,
- ups: Vec::new(),
- name: String::from(name),
- file: file.to_owned(),
- ops: Vec::new(),
- last_line_offset: 0,
- line_offsets: HashMap::new(),
- line,
- }
- }
-
- pub fn from_type(ty: &Type) -> Self {
- let mut block = Block::new("/empty/", Path::new(""), 0);
- block.ty = ty.clone();
- block
- }
-
- pub fn args(&self) -> &Vec<Type> {
- if let Type::Function(ref args, _) = self.ty {
- args
- } else {
- unreachable!()
- }
- }
-
- pub fn ret(&self) -> &Type {
- if let Type::Function(_, ref ret) = self.ty {
- ret
- } else {
- unreachable!()
- }
- }
-
- pub fn id(&self) -> (PathBuf, usize) {
- (self.file.clone(), self.line)
- }
-
- pub fn last_op(&self) -> Option<&Op> {
- self.ops.last()
- }
-
- pub fn add_line(&mut self, token_position: usize) {
- if token_position != self.last_line_offset {
- self.line_offsets.insert(self.curr(), token_position);
- self.last_line_offset = token_position;
- }
- }
-
- pub fn line(&self, ip: usize) -> usize {
- for i in (0..=ip).rev() {
- if let Some(line) = self.line_offsets.get(&i) {
- return *line;
- }
- }
- return 0;
- }
-
- pub fn debug_print(&self) {
- println!(" === {} ===", self.name.blue());
- for (i, s) in self.ops.iter().enumerate() {
- if self.line_offsets.contains_key(&i) {
- print!("{:5} ", self.line_offsets[&i].red());
- } else {
- print!(" {} ", "|".red());
- }
- println!("{:05} {:?}", i.blue(), s);
- }
- println!("");
- }
-
- pub fn last_instruction(&mut self) -> &Op {
- self.ops.last().unwrap()
- }
-
- pub fn add(&mut self, op: Op, token_position: usize) -> usize {
- let len = self.curr();
- self.add_line(token_position);
- self.ops.push(op);
- len
- }
-
- pub fn add_from(&mut self, ops: &[Op], token_position: usize) -> usize {
- let len = self.curr();
- self.add_line(token_position);
- self.ops.extend_from_slice(ops);
- len
- }
-
- pub fn curr(&self) -> usize {
- self.ops.len()
- }
-
- pub fn patch(&mut self, op: Op, pos: usize) {
- self.ops[pos] = op;
- }
-}
-
#[derive(Debug)]
struct Frame {
stack_offset: usize,
@@ -973,8 +716,8 @@ impl VM {
#[cfg(test)]
mod tests {
mod typing {
- use crate::test_string;
use crate::error::ErrorKind;
+ use crate::test_string;
test_string!(uncallable_type, "
f := fn i: int {