From a8309ffa30e9f2a9432d9bf3d9fea5d954b1e462 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edvard=20Th=C3=B6rnros?= Date: Sat, 30 Jan 2021 09:57:50 +0100 Subject: fix closures in closure bug --- src/compiler.rs | 5 ++++- src/vm.rs | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index 347abe6..92bf3fc 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -472,6 +472,9 @@ impl Compiler { let mut return_type = Type::Void; let mut function_block = Block::new(&name, &self.current_file, self.line()); + let block_id = self.blocks.len(); + self.blocks.push(Rc::new(RefCell::new(Block::new(&name, &self.current_file, self.line())))); + let _ret = push_frame!(self, function_block, { loop { match self.peek() { @@ -538,8 +541,8 @@ impl Compiler { let func = Op::Constant(Value::Function(Vec::new(), Rc::clone(&function_block))); + self.blocks[block_id] = function_block; block.add(func, self.line()); - self.blocks.push(function_block); } fn variable_expression(&mut self, block: &mut Block) { diff --git a/src/vm.rs b/src/vm.rs index 849aaa1..e2b9e57 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -470,9 +470,9 @@ impl VM { self.stack.push(Value::Function(Vec::new(), block.clone())); let mut types = Vec::new(); - for (slot, is_up, _) in block.borrow().ups.iter() { + for (slot, is_up, ty) in block.borrow().ups.iter() { if *is_up { - types.push(Type::Void); + types.push(ty.clone()); } else { types.push(self.stack[*slot].as_type()); } -- cgit v1.2.1 From 1a82b85817646aded501051f4e9d651f7c0d4970 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edvard=20Th=C3=B6rnros?= Date: Sat, 30 Jan 2021 18:42:11 +0100 Subject: tuple values --- src/compiler.rs | 47 ++++++++++++++++++++++++++++++++++++++++++++++- src/lib.rs | 23 +++++++++++------------ src/vm.rs | 5 +++++ 3 files changed, 62 insertions(+), 13 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index 92bf3fc..6fc8e78 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -284,7 +284,7 @@ impl Compiler { fn prefix(&mut self, token: Token, block: &mut Block) -> bool { match token { Token::Identifier(_) => self.variable_expression(block), - Token::LeftParen => self.grouping(block), + Token::LeftParen => self.grouping_or_tuple(block), Token::Minus => self.unary(block), Token::Float(_) => self.value(block), @@ -331,6 +331,51 @@ impl Compiler { block.add(Op::Constant(value), self.line()); } + fn grouping_or_tuple(&mut self, block: &mut Block) { + let block_length = block.ops.len(); + let token_length = self.curr; + if self.try_tuple(block).is_err() { + block.ops.truncate(block_length); + self.curr = token_length; + self.grouping(block); + } + } + + fn try_tuple(&mut self, block: &mut Block) -> Result<(), ()> { + expect!(self, Token::LeftParen, "Expected '(' at start of tuple"); + + let mut num_args = 0; + loop { + match self.peek() { + Token::RightParen | Token::EOF => { + break; + } + Token::Newline => { + self.eat(); + } + _ => { + self.expression(block); + num_args += 1; + if self.peek() == Token::Comma { + self.eat(); + continue; + } + if self.peek() == Token::RightParen { + continue; + } + return Err(()); + } + } + } + if num_args == 1 { + return Err(()); + } + + expect!(self, Token::RightParen, "Expected ')' after tuple"); + block.add(Op::Tuple(num_args), self.line()); + Ok(()) + } + fn grouping(&mut self, block: &mut Block) { expect!(self, Token::LeftParen, "Expected '(' around expression."); diff --git a/src/lib.rs b/src/lib.rs index bdd4ae4..248a589 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -314,6 +314,7 @@ a() <=> 4 pub enum Value { Blob(usize), BlobInstance(usize, Rc>>), + Tuple(Rc>), Float(f64), Int(i64), Bool(bool), @@ -378,6 +379,7 @@ impl Debug for Value { Value::ExternFunction(slot) => write!(fmt, "(extern fn {})", slot), Value::Unkown => write!(fmt, "(unkown)"), Value::Nil => write!(fmt, "(nil)"), + Value::Tuple(v) => write!(fmt, "({:?})", v), } } } @@ -393,18 +395,7 @@ impl Value { } 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, - } + Type::from(self) } } @@ -415,6 +406,7 @@ pub enum Op { Pop, PopUpvalue, Constant(Value), + Tuple(usize), Get(String), Set(String), @@ -582,6 +574,7 @@ pub enum Type { Float, Bool, String, + Tuple(Vec), Function(Vec, Box), Blob(usize), BlobInstance(usize), @@ -609,6 +602,9 @@ impl From<&Value> for Type { match value { Value::BlobInstance(i, _) => Type::BlobInstance(*i), Value::Blob(i) => Type::Blob(*i), + Value::Tuple(v) => { + Type::Tuple(v.iter().map(|x| Type::from(x)).collect()) + } Value::Int(_) => Type::Int, Value::Float(_) => Type::Float, Value::Bool(_) => Type::Bool, @@ -632,6 +628,9 @@ impl Type { Type::Void => Value::Nil, Type::Blob(i) => Value::Blob(*i), Type::BlobInstance(i) => Value::BlobInstance(*i, Rc::new(RefCell::new(Vec::new()))), + Type::Tuple(fields) => { + Value::Tuple(Rc::new(fields.iter().map(|x| x.as_value()).collect())) + } Type::UnknownType => Value::Unkown, Type::Int => Value::Int(1), Type::Float => Value::Float(1.0), diff --git a/src/vm.rs b/src/vm.rs index e2b9e57..fa998b8 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -139,6 +139,11 @@ impl VM { self.stack.pop().unwrap(); } + 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.stack.pop().unwrap(); let slot = self.stack.len(); -- cgit v1.2.1 From 4253c1c20013ab16564aa3ec34585dd1a358d182 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edvard=20Th=C3=B6rnros?= Date: Sat, 30 Jan 2021 22:34:19 +0100 Subject: add in tuples --- src/compiler.rs | 27 +++++++++++++++++++++++++++ src/error.rs | 6 ++++++ src/lib.rs | 4 ++++ src/vm.rs | 28 ++++++++++++++++++++++++---- 4 files changed, 61 insertions(+), 4 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index 6fc8e78..0ddae1a 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -315,6 +315,8 @@ impl Compiler { | Token::NotEqual => self.binary(block), + Token::LeftBracket => self.index(block), + _ => { return false; }, } return true; @@ -384,6 +386,15 @@ impl Compiler { expect!(self, Token::RightParen, "Expected ')' around expression."); } + fn index(&mut self, block: &mut Block) { + expect!(self, Token::LeftBracket, "Expected ']' around index."); + + self.expression(block); + block.add(Op::Index, self.line()); + + expect!(self, Token::RightBracket, "Expected '[' around index."); + } + fn unary(&mut self, block: &mut Block) { let op = match self.eat() { Token::Minus => Op::Neg, @@ -797,6 +808,22 @@ impl Compiler { let f = Type::Function(params, Box::new(return_type)); Ok(f) } + Token::LeftParen => { + self.eat(); + let mut element = Vec::new(); + loop { + element.push(self.parse_type()?); + if self.peek() == Token::RightParen { + self.eat(); + return Ok(Type::Tuple(element)); + } + if !expect!(self, + Token::Comma, + "Expect comma efter element in tuple.") { + return Err(()); + } + } + } Token::Identifier(x) => { self.eat(); match x.as_str() { diff --git a/src/error.rs b/src/error.rs index 2caced9..e73d863 100644 --- a/src/error.rs +++ b/src/error.rs @@ -14,6 +14,9 @@ pub enum ErrorKind { TypeError(Op, Vec), ExternTypeMismatch(String, Vec), RuntimeTypeError(Op, Vec), + + IndexOutOfBounds(Value, usize, usize), + Assert, InvalidProgram, Unreachable, @@ -38,6 +41,9 @@ impl fmt::Display for ErrorKind { .fold(String::new(), |a, v| { format!("{}{:?}, ", a, v) }); write!(f, "{} Cannot apply {:?} to types {}", "Type Error".bold(), op, types) } + ErrorKind::IndexOutOfBounds(value, len, slot) => { + write!(f, "{} for {:?} - length is {} but index is {}", "Index Error".bold(), value, len, slot) + } ErrorKind::ExternTypeMismatch(name, types) => { write!(f, "{} Extern function '{}' doesn't accept argument(s) with type(s) {:?}", "Type Error".bold(), name, types) } diff --git a/src/lib.rs b/src/lib.rs index 248a589..9a9aaa7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -408,6 +408,7 @@ pub enum Op { Constant(Value), Tuple(usize), + Index, Get(String), Set(String), @@ -590,6 +591,9 @@ impl PartialEq for Type { (Type::Float, Type::Float) => true, (Type::Bool, Type::Bool) => true, (Type::String, Type::String) => true, + (Type::Tuple(a), Type::Tuple(b)) => { + a.iter().zip(b.iter()).all(|(a, b)| a == b) + } (Type::Function(a_args, a_ret), Type::Function(b_args, b_ret)) => a_args == b_args && a_ret == b_ret, _ => false, diff --git a/src/vm.rs b/src/vm.rs index fa998b8..51d3245 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -175,6 +175,26 @@ impl VM { self.stack.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.stack.pop(); if let Some(Value::BlobInstance(ty, values)) = inst { @@ -519,14 +539,14 @@ impl VM { Op::Set(field) => { let value = self.stack.pop().unwrap(); - let inst = self.stack.pop(); - if let Some(Value::BlobInstance(ty, _)) = inst { + let inst = self.stack.pop().unwrap(); + if let Value::BlobInstance(ty, _) = inst { let ty = &self.blobs[ty].name_to_field.get(&field).unwrap().1; if ty != &Type::from(&value) { - error!(self, ErrorKind::RuntimeTypeError(Op::Set(field.clone()), vec![inst.unwrap()])); + error!(self, ErrorKind::RuntimeTypeError(Op::Set(field.clone()), vec![inst])); } } else { - error!(self, ErrorKind::RuntimeTypeError(Op::Set(field.clone()), vec![inst.unwrap()])); + error!(self, ErrorKind::RuntimeTypeError(Op::Set(field.clone()), vec![inst])); } } -- cgit v1.2.1 From 0ee362429e340d6ff67192bb2146101afcf3cb26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edvard=20Th=C3=B6rnros?= Date: Sun, 31 Jan 2021 17:01:15 +0100 Subject: add in backlogg --- TODO | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/TODO b/TODO index 84e970d..2f9af09 100644 --- a/TODO +++ b/TODO @@ -4,3 +4,24 @@ PONG - foreign structs - graphics api - parse input + +BACKLOG + - Dåliga typfelmedelanden + LESS, ADD ... + - +=, -=, ... + - constanter + - initializers + - infinet loops + - default initalization + - std-lib + - vectorer + - (1, 2) + (3, 4) = (4, 6) + - bättre rust functions länkning + - listor + - set + - escape newline + - variable not found in outer scope - SHould crash not infinet loop + - Show stack values affected + - Debugmode -- ensure stack semantics (like pop2) + - else -- syntax highlight + - automatic epsilon on floats -- cgit v1.2.1 From 28c22a38c465a68f875f27e7190703ef5da4401b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edvard=20Th=C3=B6rnros?= Date: Sun, 31 Jan 2021 17:08:41 +0100 Subject: maintain valid stack state on typeerror --- src/vm.rs | 55 ++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 44 insertions(+), 11 deletions(-) diff --git a/src/vm.rs b/src/vm.rs index 51d3245..59ad0bf 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -220,7 +220,10 @@ impl VM { match self.stack.pop().unwrap() { Value::Float(a) => self.stack.push(Value::Float(-a)), Value::Int(a) => self.stack.push(Value::Int(-a)), - a => error!(self, ErrorKind::RuntimeTypeError(op, vec![a])), + a => { + self.stack.push(Value::Nil); + error!(self, ErrorKind::RuntimeTypeError(op, vec![a])); + } } } @@ -231,7 +234,10 @@ impl VM { (Value::String(a), Value::String(b)) => { self.stack.push(Value::String(Rc::from(format!("{}{}", a, b)))) } - (a, b) => error!(self, ErrorKind::RuntimeTypeError(op, vec![a, b])), + (a, b) => { + self.stack.push(Value::Nil); + error!(self, ErrorKind::RuntimeTypeError(op, vec![a, b])); + } } } @@ -239,7 +245,10 @@ impl VM { 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) => error!(self, ErrorKind::RuntimeTypeError(op, vec![a, b])), + (a, b) => { + self.stack.push(Value::Nil); + error!(self, ErrorKind::RuntimeTypeError(op, vec![a, b])); + } } } @@ -247,7 +256,10 @@ impl VM { 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) => error!(self, ErrorKind::RuntimeTypeError(op, vec![a, b])), + (a, b) => { + self.stack.push(Value::Nil); + error!(self, ErrorKind::RuntimeTypeError(op, vec![a, b])); + } } } @@ -255,7 +267,10 @@ impl VM { 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) => error!(self, ErrorKind::RuntimeTypeError(op, vec![a, b])), + (a, b) => { + self.stack.push(Value::Nil); + error!(self, ErrorKind::RuntimeTypeError(op, vec![a, b])); + } } } @@ -265,7 +280,10 @@ impl VM { (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) => error!(self, ErrorKind::RuntimeTypeError(op, vec![a, b])), + (a, b) => { + self.stack.push(Value::Nil); + error!(self, ErrorKind::RuntimeTypeError(op, vec![a, b])); + } } } @@ -275,7 +293,10 @@ impl VM { (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) => error!(self, ErrorKind::RuntimeTypeError(op, vec![a, b])), + (a, b) => { + self.stack.push(Value::Nil); + error!(self, ErrorKind::RuntimeTypeError(op, vec![a, b])); + } } } @@ -285,28 +306,40 @@ impl VM { (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) => error!(self, ErrorKind::RuntimeTypeError(op, vec![a, b])), + (a, b) => { + self.stack.push(Value::Nil); + error!(self, ErrorKind::RuntimeTypeError(op, vec![a, b])); + } } } Op::And => { match self.pop_twice() { (Value::Bool(a), Value::Bool(b)) => self.stack.push(Value::Bool(a && b)), - (a, b) => error!(self, ErrorKind::RuntimeTypeError(op, vec![a, b])), + (a, b) => { + self.stack.push(Value::Nil); + error!(self, ErrorKind::RuntimeTypeError(op, vec![a, b])); + } } } Op::Or => { match self.pop_twice() { (Value::Bool(a), Value::Bool(b)) => self.stack.push(Value::Bool(a || b)), - (a, b) => error!(self, ErrorKind::RuntimeTypeError(op, vec![a, b])), + (a, b) => { + self.stack.push(Value::Nil); + error!(self, ErrorKind::RuntimeTypeError(op, vec![a, b])); + } } } Op::Not => { match self.stack.pop().unwrap() { Value::Bool(a) => self.stack.push(Value::Bool(!a)), - a => error!(self, ErrorKind::RuntimeTypeError(op, vec![a])), + a => { + self.stack.push(Value::Nil); + error!(self, ErrorKind::RuntimeTypeError(op, vec![a])); + } } } -- cgit v1.2.1 From bdcdbf7d65b7a05216c33f802f1f1646e1f68718 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edvard=20Th=C3=B6rnros?= Date: Sun, 31 Jan 2021 20:25:06 +0100 Subject: basic arithmatic for tuples --- src/lib.rs | 110 ++++++++++++++++++++++++++++++++++++++++++ src/vm.rs | 158 ++++++++++++++++--------------------------------------------- 2 files changed, 151 insertions(+), 117 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 9a9aaa7..c7841f7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -384,6 +384,109 @@ impl Debug for Value { } } +mod op { + use super::Value; + use std::rc::Rc; + + fn tuple_op(a: &Rc>, b: &Rc>, f: fn (&Value, &Value) -> Value) -> Value { + Value::Tuple(Rc::new(a.iter().zip(b.iter()).map(|(a, b)| f(a, b)).collect())) + } + + pub fn neg(value: &Value) -> Value { + match value { + Value::Float(a) => Value::Float(-a), + Value::Int(a) => Value::Int(-a), + Value::Tuple(a) => Value::Tuple(Rc::new(a.iter().map(neg).collect())), + _ => Value::Nil, + } + } + + pub fn not(value: &Value) -> Value { + match value { + Value::Bool(a) => Value::Bool(!a), + Value::Tuple(a) => Value::Tuple(Rc::new(a.iter().map(not).collect())), + _ => Value::Nil, + } + } + + + pub fn add(a: &Value, b: &Value) -> Value { + match (a, b) { + (Value::Float(a), Value::Float(b)) => Value::Float(a + b), + (Value::Int(a), Value::Int(b)) => Value::Int(a + b), + (Value::String(a), Value::String(b)) => Value::String(Rc::from(format!("{}{}", a, b))), + (Value::Tuple(a), Value::Tuple(b)) if a.len() == b.len() => tuple_op(a, b, add), + _ => Value::Nil, + } + } + + pub fn sub(a: &Value, b: &Value) -> Value { + add(a, &neg(b)) + } + + pub fn mul(a: &Value, b: &Value) -> Value { + match (a, b) { + (Value::Float(a), Value::Float(b)) => Value::Float(a * b), + (Value::Int(a), Value::Int(b)) => Value::Int(a * b), + (Value::Tuple(a), Value::Tuple(b)) if a.len() == b.len() => tuple_op(a, b, mul), + _ => Value::Nil, + } + } + + pub fn div(a: &Value, b: &Value) -> Value { + match (a, b) { + (Value::Float(a), Value::Float(b)) => Value::Float(a / b), + (Value::Int(a), Value::Int(b)) => Value::Int(a / b), + (Value::Tuple(a), Value::Tuple(b)) if a.len() == b.len() => tuple_op(a, b, div), + _ => Value::Nil, + } + } + + pub fn eq(a: &Value, b: &Value) -> Value { + match (a, b) { + (Value::Float(a), Value::Float(b)) => Value::Bool(a == b), + (Value::Int(a), Value::Int(b)) => Value::Bool(a == b), + (Value::String(a), Value::String(b)) => Value::Bool(a == b), + (Value::Bool(a), Value::Bool(b)) => Value::Bool(a == b), + (Value::Tuple(a), Value::Tuple(b)) if a.len() == b.len() => tuple_op(a, b, eq), + _ => Value::Nil, + } + } + + pub fn less(a: &Value, b: &Value) -> Value { + match (a, b) { + (Value::Float(a), Value::Float(b)) => Value::Bool(a < b), + (Value::Int(a), Value::Int(b)) => Value::Bool(a < b), + (Value::String(a), Value::String(b)) => Value::Bool(a < b), + (Value::Bool(a), Value::Bool(b)) => Value::Bool(a < b), + (Value::Tuple(a), Value::Tuple(b)) if a.len() == b.len() => tuple_op(a, b, less), + _ => Value::Nil, + } + } + + pub fn greater(a: &Value, b: &Value) -> Value { + less(b, a) + } + + pub fn and(a: &Value, b: &Value) -> Value { + match (a, b) { + (Value::Bool(a), Value::Bool(b)) => Value::Bool(*a && *b), + (Value::Tuple(a), Value::Tuple(b)) if a.len() == b.len() => tuple_op(a, b, and), + _ => Value::Nil, + } + } + + pub fn or(a: &Value, b: &Value) -> Value { + match (a, b) { + (Value::Bool(a), Value::Bool(b)) => Value::Bool(*a || *b), + (Value::Tuple(a), Value::Tuple(b)) if a.len() == b.len() => tuple_op(a, b, or), + _ => Value::Nil, + } + } + +} + + impl Value { fn identity(self) -> Self { match self { @@ -394,6 +497,13 @@ impl Value { } } + fn is_nil(&self) -> bool { + match self { + Value::Nil => true, + _ => false, + } + } + fn as_type(&self) -> Type { Type::from(self) } 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; -- cgit v1.2.1 From 0499cbf559fee79ec895dbbe30b9fed5962426ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edvard=20Th=C3=B6rnros?= Date: Sun, 31 Jan 2021 20:53:18 +0100 Subject: tuple tests --- src/lib.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index c7841f7..d07f2a3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -306,6 +306,14 @@ a() <=> 4 5 <=> a.a + a.b" ); + test_multiple!(tuples, + add: "(1, 2, 3, 4) + (4, 3, 2, 1) <=> (5, 5, 5, 5)", + sub: "(1, -2, 3, -4) - (4, 3, -2, -1) <=> (-3, 1, 1, -5)", + mul: "(0, 1, 2) * (2, 3, 4) <=> (0, 3, 8)", + types: "a: (int, float, int) = (1, 1., 1)", + more_types: "a: (str, bool, int) = (\"abc\", true, 1)", + ); + test_file!(scoping, "tests/scoping.tdy"); test_file!(for_, "tests/for.tdy"); } -- cgit v1.2.1 From 58a41961dccf08171eba6aeb7f16f0a7f5750d14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edvard=20Th=C3=B6rnros?= Date: Mon, 1 Feb 2021 10:40:02 +0100 Subject: simplify try_tuple from feedback --- src/compiler.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index 0ddae1a..f4bec9a 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -358,14 +358,11 @@ impl Compiler { _ => { self.expression(block); num_args += 1; - if self.peek() == Token::Comma { - self.eat(); - continue; - } - if self.peek() == Token::RightParen { - continue; + match self.peek() { + Token::Comma => { self.eat(); }, + Token::RightParen => {}, + _ => { return Err(()); }, } - return Err(()); } } } -- cgit v1.2.1 From ae48928ebdaf809c9191067cd3226e1a1a2b67d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edvard=20Th=C3=B6rnros?= Date: Mon, 1 Feb 2021 10:42:25 +0100 Subject: fix index brace order --- src/compiler.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index f4bec9a..79d14b6 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -384,12 +384,12 @@ impl Compiler { } fn index(&mut self, block: &mut Block) { - expect!(self, Token::LeftBracket, "Expected ']' around index."); + expect!(self, Token::LeftBracket, "Expected '[' around index."); self.expression(block); block.add(Op::Index, self.line()); - expect!(self, Token::RightBracket, "Expected '[' around index."); + expect!(self, Token::RightBracket, "Expected ']' around index."); } fn unary(&mut self, block: &mut Block) { -- cgit v1.2.1 From 23866f117ace6b4e0b2cd3c611cdb982cf20e4ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edvard=20Th=C3=B6rnros?= Date: Mon, 1 Feb 2021 10:47:55 +0100 Subject: fix compiler warning --- src/compiler.rs | 3 ++- src/vm.rs | 6 ------ 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index 79d14b6..b76e1b2 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -526,7 +526,8 @@ impl Compiler { let mut function_block = Block::new(&name, &self.current_file, self.line()); let block_id = self.blocks.len(); - self.blocks.push(Rc::new(RefCell::new(Block::new(&name, &self.current_file, self.line())))); + let temp_block = Block::new(&name, &self.current_file, self.line()); + self.blocks.push(Rc::new(RefCell::new(temp_block))); let _ret = push_frame!(self, function_block, { loop { diff --git a/src/vm.rs b/src/vm.rs index dd233dc..ea15b5d 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -119,12 +119,6 @@ impl VM { 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)); - (b, a) // this matches the order they were on the stack - } - fn _peek_up(&self, amount: usize) -> Option<&Value> { self.stack.get(self.stack.len() - amount) } -- cgit v1.2.1 From c28590d98a5beb176e2f92915faa894be06238f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edvard=20Th=C3=B6rnros?= Date: Mon, 1 Feb 2021 11:25:10 +0100 Subject: use poppop --- src/vm.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/vm.rs b/src/vm.rs index ea15b5d..485d449 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -34,8 +34,7 @@ macro_rules! one_op { macro_rules! two_op { ( $self:expr, $op:expr, $fun:expr ) => { - let b = $self.pop(); - let a = $self.pop(); + let (a, b) = $self.poppop(); let c = $fun(&a, &b); if c.is_nil() { $self.push(c); @@ -115,6 +114,12 @@ impl VM { self.stack.pop().unwrap() } + fn poppop(&mut self) -> (Value, Value) { + let (a, b) = (self.stack.remove(self.stack.len() - 1), + self.stack.remove(self.stack.len() - 1)); + (b, a) // this matches the order they were on the stack + } + fn push(&mut self, value: Value) { self.stack.push(value) } -- cgit v1.2.1 From e9ce94d72e1e8e51b7843b414504a07e132813e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edvard=20Th=C3=B6rnros?= Date: Mon, 1 Feb 2021 11:27:12 +0100 Subject: add the missing '.' --- src/compiler.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler.rs b/src/compiler.rs index b76e1b2..6c01ea3 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -370,7 +370,7 @@ impl Compiler { return Err(()); } - expect!(self, Token::RightParen, "Expected ')' after tuple"); + expect!(self, Token::RightParen, "Expected ')' after tuple."); block.add(Op::Tuple(num_args), self.line()); Ok(()) } -- cgit v1.2.1