aboutsummaryrefslogtreecommitdiffstats
path: root/src/compiler.rs
diff options
context:
space:
mode:
authorGustav Sörnäs <gustav@sornas.net>2021-01-28 21:53:21 +0100
committerGustav Sörnäs <gustav@sornas.net>2021-01-28 21:53:21 +0100
commit0159d05e183f58ae81d4697e0b178a487f0bde34 (patch)
tree838d4ffd6a3da11f3333e1371452dc7ed54f3bf0 /src/compiler.rs
parentfddd4555f7162fb64b1fa1b57282de63d0f4d452 (diff)
downloadsylt-0159d05e183f58ae81d4697e0b178a487f0bde34.tar.gz
assign (ish) to blob fields
Diffstat (limited to 'src/compiler.rs')
-rw-r--r--src/compiler.rs49
1 files changed, 47 insertions, 2 deletions
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();