From 0159d05e183f58ae81d4697e0b178a487f0bde34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustav=20S=C3=B6rn=C3=A4s?= Date: Thu, 28 Jan 2021 21:53:21 +0100 Subject: assign (ish) to blob fields --- src/compiler.rs | 49 +++++++++++++++++++++++++++++++++++++++++++++++-- src/vm.rs | 13 +++++++++++++ 2 files changed, 60 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/compiler.rs b/src/compiler.rs index 256ce49..431a762 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -657,7 +657,7 @@ impl Compiler { if let Token::Identifier(field) = self.eat() { block.add(Op::Get(String::from(field)), self.line()); } else { - error!(self, "Expected fieldname after '.'"); + error!(self, "Expected fieldname after '.'."); break; } } @@ -900,6 +900,47 @@ impl Compiler { self.blobs.push(blob); } + fn blob_field(&mut self, block: &mut Block) { + let name = match self.eat() { + Token::Identifier(name) => name, + _ => unreachable!(), + }; + if let Some(var) = self.find_variable(&name) { + if var.upvalue { + block.add(Op::ReadUpvalue(var.slot), self.line()); + } else { + block.add(Op::ReadLocal(var.slot), self.line()); + } + loop { + match self.peek() { + Token::Dot => { + self.eat(); + let field = if let Token::Identifier(field) = self.eat() { + String::from(field) + } else { + error!(self, "Expected fieldname after '.'."); + return; + }; + + if self.peek() == Token::Equal { + self.eat(); + self.expression(block); + block.add(Op::Set(field), self.line()); + } else { + block.add(Op::Get(field), self.line()); + } + } + Token::LeftParen => { + self.call(block); + } + _ => { break } + } + } + } else { + error!(self, format!("Using undefined variable {}.", name)); + } + } + fn statement(&mut self, block: &mut Block) { self.clear_panic(); @@ -908,7 +949,11 @@ impl Compiler { self.eat(); self.expression(block); block.add(Op::Print, self.line()); - }, + } + + (Token::Identifier(_), Token::Dot, ..) => { + self.blob_field(block); + } (Token::Identifier(name), Token::Colon, ..) => { self.eat(); diff --git a/src/vm.rs b/src/vm.rs index 028f2cd..5b0abae 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -122,7 +122,9 @@ pub enum Op { Pop, PopUpvalue, Constant(Value), + Get(String), + Set(String), Add, Sub, @@ -426,6 +428,17 @@ impl VM { } } + Op::Set(field) => { + let value = self.stack.pop().unwrap(); + let inst = self.stack.pop(); + if let Some(Value::BlobInstance(ty, mut values)) = inst { + let slot = self.blobs[ty].name_to_field.get(&field).unwrap().0; + values[slot] = value; + } else { + error!(self, ErrorKind::RuntimeTypeError(Op::Get(field.clone()), vec![inst.unwrap()])); + } + } + Op::Neg => { match self.stack.pop().unwrap() { Value::Float(a) => self.stack.push(Value::Float(-a)), -- cgit v1.2.1