aboutsummaryrefslogtreecommitdiffstats
path: root/src/vm.rs
diff options
context:
space:
mode:
authorEdvard Thörnros <edvard.thornros@gmail.com>2021-02-01 21:44:31 +0100
committerGitHub <noreply@github.com>2021-02-01 21:44:31 +0100
commit8089ff61f5ca608e0801e74360203c6fd789b5d7 (patch)
tree4ee11f40d2be5c99739ae39a556396bcdc5f291c /src/vm.rs
parent354be47619650cd85c1de2a546139c092a88c80f (diff)
parent82919eabb21a6df3e57b46912c4513dbd56df827 (diff)
downloadsylt-8089ff61f5ca608e0801e74360203c6fd789b5d7.tar.gz
Merge pull request #3 from FredTheDino/vectors
vectors
Diffstat (limited to 'src/vm.rs')
-rw-r--r--src/vm.rs149
1 files changed, 63 insertions, 86 deletions
diff --git a/src/vm.rs b/src/vm.rs
index 6ff7b65..221c3e0 100644
--- a/src/vm.rs
+++ b/src/vm.rs
@@ -6,7 +6,7 @@ use std::rc::Rc;
use owo_colors::OwoColorize;
-use crate::{Blob, Block, Op, Prog, UpValue, Value};
+use crate::{Blob, Block, Op, Prog, UpValue, Value, op};
use crate::error::{Error, ErrorKind};
use crate::RustFunction;
pub use crate::Type;
@@ -20,6 +20,30 @@ macro_rules! error {
};
}
+macro_rules! one_op {
+ ( $self:expr, $op:expr, $fun:expr ) => {
+ let a = $self.pop();
+ let b = $fun(&a);
+ if b.is_nil() {
+ $self.push(b);
+ error!($self, ErrorKind::RuntimeTypeError($op, vec![a]));
+ }
+ $self.push(b);
+ };
+}
+
+macro_rules! two_op {
+ ( $self:expr, $op:expr, $fun:expr ) => {
+ let (a, b) = $self.poppop();
+ let c = $fun(&a, &b);
+ if c.is_nil() {
+ $self.push(c);
+ error!($self, ErrorKind::RuntimeTypeError($op, vec![a, b]));
+ }
+ $self.push(c);
+ };
+}
+
#[derive(Debug)]
struct Frame {
stack_offset: usize,
@@ -159,6 +183,11 @@ impl VM {
self.pop();
}
+ Op::Tuple(size) => {
+ let values = self.stack.split_off(self.stack.len() - size);
+ self.stack.push(Value::Tuple(Rc::new(values)));
+ }
+
Op::PopUpvalue => {
let value = self.pop();
let slot = self.stack.len();
@@ -201,6 +230,26 @@ impl VM {
self.push(value);
}
+ Op::Index => {
+ let slot = self.stack.pop().unwrap();
+ let val = self.stack.pop().unwrap();
+ match (val, slot) {
+ (Value::Tuple(v), Value::Int(slot)) => {
+ let slot = slot as usize;
+ if v.len() < slot {
+ self.stack.push(Value::Nil);
+ let len = v.len();
+ error!(self, ErrorKind::IndexOutOfBounds(Value::Tuple(v), len, slot));
+ }
+ self.stack.push(v[slot].clone());
+ }
+ (val, slot) => {
+ self.stack.push(Value::Nil);
+ error!(self, ErrorKind::RuntimeTypeError(op, vec![val, slot]), String::from("Cannot index type"));
+ }
+ }
+ }
+
Op::Get(field) => {
let inst = self.pop();
if let Value::BlobInstance(ty, values) = inst {
@@ -212,8 +261,7 @@ impl VM {
}
Op::Set(field) => {
- let value = self.pop();
- let inst = self.pop();
+ let (inst, value) = self.poppop();
if let Value::BlobInstance(ty, values) = inst {
let slot = self.blobs[ty].name_to_field.get(&field).unwrap().0;
values.borrow_mut()[slot] = value;
@@ -222,99 +270,27 @@ impl VM {
}
}
- Op::Neg => {
- match self.pop() {
- Value::Float(a) => self.push(Value::Float(-a)),
- Value::Int(a) => self.push(Value::Int(-a)),
- a => error!(self, ErrorKind::RuntimeTypeError(op, vec![a])),
- }
- }
+ Op::Neg => { one_op!(self, Op::Neg, op::neg); }
- Op::Add => {
- match self.poppop() {
- (Value::Float(a), Value::Float(b)) => self.push(Value::Float(a + b)),
- (Value::Int(a), Value::Int(b)) => self.push(Value::Int(a + b)),
- (Value::String(a), Value::String(b)) => {
- self.push(Value::String(Rc::from(format!("{}{}", a, b))))
- }
- (a, b) => error!(self, ErrorKind::RuntimeTypeError(op, vec![a, b])),
- }
- }
+ Op::Add => { two_op!(self, Op::Add, op::add); }
- Op::Sub => {
- match self.poppop() {
- (Value::Float(a), Value::Float(b)) => self.push(Value::Float(a - b)),
- (Value::Int(a), Value::Int(b)) => self.push(Value::Int(a - b)),
- (a, b) => error!(self, ErrorKind::RuntimeTypeError(op, vec![a, b])),
- }
- }
+ Op::Sub => { two_op!(self, Op::Sub, op::sub); }
- Op::Mul => {
- match self.poppop() {
- (Value::Float(a), Value::Float(b)) => self.push(Value::Float(a * b)),
- (Value::Int(a), Value::Int(b)) => self.push(Value::Int(a * b)),
- (a, b) => error!(self, ErrorKind::RuntimeTypeError(op, vec![a, b])),
- }
- }
+ Op::Mul => { two_op!(self, Op::Mul, op::mul); }
- Op::Div => {
- match self.poppop() {
- (Value::Float(a), Value::Float(b)) => self.push(Value::Float(a / b)),
- (Value::Int(a), Value::Int(b)) => self.push(Value::Int(a / b)),
- (a, b) => error!(self, ErrorKind::RuntimeTypeError(op, vec![a, b])),
- }
- }
+ Op::Div => { two_op!(self, Op::Div, op::div); }
- Op::Equal => {
- match self.poppop() {
- (Value::Float(a), Value::Float(b)) => self.push(Value::Bool(a == b)),
- (Value::Int(a), Value::Int(b)) => self.push(Value::Bool(a == b)),
- (Value::String(a), Value::String(b)) => self.push(Value::Bool(a == b)),
- (Value::Bool(a), Value::Bool(b)) => self.push(Value::Bool(a == b)),
- (a, b) => error!(self, ErrorKind::RuntimeTypeError(op, vec![a, b])),
- }
- }
+ Op::Equal => { two_op!(self, Op::Equal, op::eq); }
- Op::Less => {
- match self.poppop() {
- (Value::Float(a), Value::Float(b)) => self.push(Value::Bool(a < b)),
- (Value::Int(a), Value::Int(b)) => self.push(Value::Bool(a < b)),
- (Value::String(a), Value::String(b)) => self.push(Value::Bool(a < b)),
- (Value::Bool(a), Value::Bool(b)) => self.push(Value::Bool(a < b)),
- (a, b) => error!(self, ErrorKind::RuntimeTypeError(op, vec![a, b])),
- }
- }
+ Op::Less => { two_op!(self, Op::Less, op::less); }
- Op::Greater => {
- match self.poppop() {
- (Value::Float(a), Value::Float(b)) => self.push(Value::Bool(a > b)),
- (Value::Int(a), Value::Int(b)) => self.push(Value::Bool(a > b)),
- (Value::String(a), Value::String(b)) => self.push(Value::Bool(a > b)),
- (Value::Bool(a), Value::Bool(b)) => self.push(Value::Bool(a > b)),
- (a, b) => error!(self, ErrorKind::RuntimeTypeError(op, vec![a, b])),
- }
- }
+ Op::Greater => { two_op!(self, Op::Greater, op::greater); }
- Op::And => {
- match self.poppop() {
- (Value::Bool(a), Value::Bool(b)) => self.push(Value::Bool(a && b)),
- (a, b) => error!(self, ErrorKind::RuntimeTypeError(op, vec![a, b])),
- }
- }
+ Op::And => { two_op!(self, Op::And, op::and); }
- Op::Or => {
- match self.poppop() {
- (Value::Bool(a), Value::Bool(b)) => self.push(Value::Bool(a || b)),
- (a, b) => error!(self, ErrorKind::RuntimeTypeError(op, vec![a, b])),
- }
- }
+ Op::Or => { two_op!(self, Op::Or, op::or); }
- Op::Not => {
- match self.pop() {
- Value::Bool(a) => self.push(Value::Bool(!a)),
- a => error!(self, ErrorKind::RuntimeTypeError(op, vec![a])),
- }
- }
+ Op::Not => { one_op!(self, Op::Not, op::not); }
Op::Jmp(line) => {
self.frame_mut().ip = line;
@@ -552,6 +528,7 @@ impl VM {
Op::Set(field) => {
let value = self.pop();
let inst = self.pop();
+
if let Value::BlobInstance(ty, _) = inst {
let ty = &self.blobs[ty].name_to_field.get(&field).unwrap().1;
if ty != &Type::from(&value) {