aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEdvard Thörnros <edvard.thornros@gmail.com>2021-01-30 18:42:11 +0100
committerEdvard Thörnros <edvard.thornros@gmail.com>2021-01-30 18:42:11 +0100
commit1a82b85817646aded501051f4e9d651f7c0d4970 (patch)
tree14d8bf49f94a0eac515ba0fc9e8c39733643477b
parenta8309ffa30e9f2a9432d9bf3d9fea5d954b1e462 (diff)
downloadsylt-1a82b85817646aded501051f4e9d651f7c0d4970.tar.gz
tuple values
-rw-r--r--src/compiler.rs47
-rw-r--r--src/lib.rs23
-rw-r--r--src/vm.rs5
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<RefCell<Vec<Value>>>),
+ Tuple(Rc<Vec<Value>>),
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<Type>),
Function(Vec<Type>, Box<Type>),
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();