aboutsummaryrefslogtreecommitdiffstats
path: root/src/vm.rs
diff options
context:
space:
mode:
authorEdvard Thörnros <edvard.thornros@gmail.com>2021-01-31 20:25:06 +0100
committerEdvard Thörnros <edvard.thornros@gmail.com>2021-01-31 20:25:06 +0100
commitbdcdbf7d65b7a05216c33f802f1f1646e1f68718 (patch)
treebd8bc20f2f7200e30fe19381e611f89fd03800b3 /src/vm.rs
parent28c22a38c465a68f875f27e7190703ef5da4401b (diff)
downloadsylt-bdcdbf7d65b7a05216c33f802f1f1646e1f68718.tar.gz
basic arithmatic for tuples
Diffstat (limited to 'src/vm.rs')
-rw-r--r--src/vm.rs158
1 files changed, 41 insertions, 117 deletions
diff --git a/src/vm.rs b/src/vm.rs
index 59ad0bf..dd233dc 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,31 @@ 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 b = $self.pop();
+ let a = $self.pop();
+ 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,
@@ -90,6 +115,10 @@ impl VM {
self.stack.pop().unwrap()
}
+ fn push(&mut self, value: Value) {
+ self.stack.push(value)
+ }
+
fn pop_twice(&mut self) -> (Value, Value) {
let (a, b) = (self.stack.remove(self.stack.len() - 1),
self.stack.remove(self.stack.len() - 1));
@@ -216,132 +245,27 @@ impl VM {
}
}
- Op::Neg => {
- match self.stack.pop().unwrap() {
- Value::Float(a) => self.stack.push(Value::Float(-a)),
- Value::Int(a) => self.stack.push(Value::Int(-a)),
- a => {
- self.stack.push(Value::Nil);
- error!(self, ErrorKind::RuntimeTypeError(op, vec![a]));
- }
- }
- }
+ Op::Neg => { one_op!(self, Op::Neg, op::neg); }
- Op::Add => {
- match self.pop_twice() {
- (Value::Float(a), Value::Float(b)) => self.stack.push(Value::Float(a + b)),
- (Value::Int(a), Value::Int(b)) => self.stack.push(Value::Int(a + b)),
- (Value::String(a), Value::String(b)) => {
- self.stack.push(Value::String(Rc::from(format!("{}{}", a, b))))
- }
- (a, b) => {
- self.stack.push(Value::Nil);
- error!(self, ErrorKind::RuntimeTypeError(op, vec![a, b]));
- }
- }
- }
+ Op::Add => { two_op!(self, Op::Add, op::add); }
- Op::Sub => {
- match self.pop_twice() {
- (Value::Float(a), Value::Float(b)) => self.stack.push(Value::Float(a - b)),
- (Value::Int(a), Value::Int(b)) => self.stack.push(Value::Int(a - b)),
- (a, b) => {
- self.stack.push(Value::Nil);
- error!(self, ErrorKind::RuntimeTypeError(op, vec![a, b]));
- }
- }
- }
+ Op::Sub => { two_op!(self, Op::Sub, op::sub); }
- Op::Mul => {
- match self.pop_twice() {
- (Value::Float(a), Value::Float(b)) => self.stack.push(Value::Float(a * b)),
- (Value::Int(a), Value::Int(b)) => self.stack.push(Value::Int(a * b)),
- (a, b) => {
- self.stack.push(Value::Nil);
- error!(self, ErrorKind::RuntimeTypeError(op, vec![a, b]));
- }
- }
- }
+ Op::Mul => { two_op!(self, Op::Mul, op::mul); }
- Op::Div => {
- match self.pop_twice() {
- (Value::Float(a), Value::Float(b)) => self.stack.push(Value::Float(a / b)),
- (Value::Int(a), Value::Int(b)) => self.stack.push(Value::Int(a / b)),
- (a, b) => {
- self.stack.push(Value::Nil);
- error!(self, ErrorKind::RuntimeTypeError(op, vec![a, b]));
- }
- }
- }
+ Op::Div => { two_op!(self, Op::Div, op::div); }
- Op::Equal => {
- match self.pop_twice() {
- (Value::Float(a), Value::Float(b)) => self.stack.push(Value::Bool(a == b)),
- (Value::Int(a), Value::Int(b)) => self.stack.push(Value::Bool(a == b)),
- (Value::String(a), Value::String(b)) => self.stack.push(Value::Bool(a == b)),
- (Value::Bool(a), Value::Bool(b)) => self.stack.push(Value::Bool(a == b)),
- (a, b) => {
- self.stack.push(Value::Nil);
- error!(self, ErrorKind::RuntimeTypeError(op, vec![a, b]));
- }
- }
- }
+ Op::Equal => { two_op!(self, Op::Equal, op::eq); }
- Op::Less => {
- match self.pop_twice() {
- (Value::Float(a), Value::Float(b)) => self.stack.push(Value::Bool(a < b)),
- (Value::Int(a), Value::Int(b)) => self.stack.push(Value::Bool(a < b)),
- (Value::String(a), Value::String(b)) => self.stack.push(Value::Bool(a < b)),
- (Value::Bool(a), Value::Bool(b)) => self.stack.push(Value::Bool(a < b)),
- (a, b) => {
- self.stack.push(Value::Nil);
- error!(self, ErrorKind::RuntimeTypeError(op, vec![a, b]));
- }
- }
- }
+ Op::Less => { two_op!(self, Op::Less, op::less); }
- Op::Greater => {
- match self.pop_twice() {
- (Value::Float(a), Value::Float(b)) => self.stack.push(Value::Bool(a > b)),
- (Value::Int(a), Value::Int(b)) => self.stack.push(Value::Bool(a > b)),
- (Value::String(a), Value::String(b)) => self.stack.push(Value::Bool(a > b)),
- (Value::Bool(a), Value::Bool(b)) => self.stack.push(Value::Bool(a > b)),
- (a, b) => {
- self.stack.push(Value::Nil);
- error!(self, ErrorKind::RuntimeTypeError(op, vec![a, b]));
- }
- }
- }
+ Op::Greater => { two_op!(self, Op::Greater, op::greater); }
- Op::And => {
- match self.pop_twice() {
- (Value::Bool(a), Value::Bool(b)) => self.stack.push(Value::Bool(a && b)),
- (a, b) => {
- self.stack.push(Value::Nil);
- error!(self, ErrorKind::RuntimeTypeError(op, vec![a, b]));
- }
- }
- }
+ Op::And => { two_op!(self, Op::And, op::and); }
- Op::Or => {
- match self.pop_twice() {
- (Value::Bool(a), Value::Bool(b)) => self.stack.push(Value::Bool(a || b)),
- (a, b) => {
- self.stack.push(Value::Nil);
- error!(self, ErrorKind::RuntimeTypeError(op, vec![a, b]));
- }
- }
- }
+ Op::Or => { two_op!(self, Op::Or, op::or); }
- Op::Not => {
- match self.stack.pop().unwrap() {
- Value::Bool(a) => self.stack.push(Value::Bool(!a)),
- a => {
- self.stack.push(Value::Nil);
- error!(self, ErrorKind::RuntimeTypeError(op, vec![a]));
- }
- }
- }
+ Op::Not => { one_op!(self, Op::Not, op::not); }
Op::Jmp(line) => {
self.frame_mut().ip = line;