From 651865f41eea7a64093724ad664646eb76100ab1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edvard=20Th=C3=B6rnros?= Date: Wed, 10 Feb 2021 23:01:35 +0100 Subject: add constants --- src/compiler.rs | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) (limited to 'src') diff --git a/src/compiler.rs b/src/compiler.rs index 7f0d32d..d18d9c6 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -126,6 +126,7 @@ struct Variable { active: bool, upvalue: bool, captured: bool, + mutable: bool, } struct Frame { @@ -759,6 +760,32 @@ impl Compiler { scope, active: false, upvalue: false, + mutable: true, + }); + Ok(slot) + } + + fn define_constant(&mut self, name: &str, typ: Type, _block: &mut Block) -> Result { + if let Some(var) = self.find_variable(&name) { + if var.scope == self.frame().scope { + error!(self, format!("Multiple definitions of {} in this block.", name)); + return Err(()); + } + } + + let slot = self.stack().len(); + let scope = self.frame().scope; + self.stack_mut().push(Variable { + name: String::from(name), + captured: false, + outer_upvalue: false, + outer_slot: 0, + slot, + typ, + scope, + active: false, + upvalue: false, + mutable: false, }); Ok(slot) } @@ -774,6 +801,15 @@ impl Compiler { } } + fn constant_statement(&mut self, name: &str, typ: Type, block: &mut Block) { + let slot = self.define_constant(name, typ.clone(), block); + self.expression(block); + + if let Ok(slot) = slot { + self.stack_mut()[slot].active = true; + } + } + fn assign(&mut self, block: &mut Block) { let name = match self.eat() { Token::Identifier(name) => name, @@ -798,6 +834,10 @@ impl Compiler { }; if let Some(var) = self.find_variable(&name) { + if !var.mutable { + // TODO(ed): Maybe a better error than "SyntaxError". + error!(self, format!("Cannot assign to constant '{}'", var.name)); + } if let Some(op) = op { add_op(self, block, Op::Copy); self.expression(block); @@ -1123,6 +1163,12 @@ impl Compiler { self.definition_statement(&name, Type::Unknown, block); } + (Token::Identifier(name), Token::ColonColon, ..) => { + self.eat(); + self.eat(); + self.constant_statement(&name, Type::Unknown, block); + } + (Token::Blob, Token::Identifier(_), ..) => { self.blob_statement(block); } @@ -1177,6 +1223,7 @@ impl Compiler { active: false, captured: false, upvalue: false, + mutable: true, }); let mut block = Block::new(name, file, 0); -- cgit v1.2.1 From 9bd53d666c32d93b6a81a05c15025fd41bd056ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edvard=20Th=C3=B6rnros?= Date: Wed, 10 Feb 2021 23:05:45 +0100 Subject: add tests for constants --- src/lib.rs | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index ae45c45..cd84776 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -805,6 +805,16 @@ mod tests { assert_errs!(run_string("\n", true, Vec::new()), [ErrorKind::Unreachable]); } + #[test] + fn assign_to_constant() { + assert_errs!(run_string("a :: 2\na = 2", true, Vec::new()), [ErrorKind::SyntaxError(_, _)]); + } + + #[test] + fn assign_to_constant_upvalue() { + assert_errs!(run_string("a :: 2\nq :: fn { a = 2 }\n", true, Vec::new()), [ErrorKind::SyntaxError(_, _)]); + } + macro_rules! test_multiple { ($mod:ident, $( $fn:ident : $prog:literal ),+ $( , )? ) => { mod $mod { @@ -848,7 +858,7 @@ mod tests { test_multiple!( if_, compare_constants_equality: "if 1 == 2 { - + }", compare_constants_unequality: "if 1 != 1 { @@ -1050,4 +1060,16 @@ a.a <=> 0" simple: "a := 1 // blargh \na += 1 // blargh \n a <=> 2 // HARGH", expressions: "1 + 1 // blargh \n 2 // blargh \n // HARGH \n", ); + + test_multiple!( + read_constants, + simple: " +a :: 1 +a <=> 1 +b := 2 +{ + a <=> 1 +} +", + ); } -- cgit v1.2.1 From 089d018fdc5a76508aba27292ba379d5691cbc3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edvard=20Th=C3=B6rnros?= Date: Thu, 11 Feb 2021 18:15:47 +0100 Subject: fix feedback from codereview --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index cd84776..3f753f1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -858,7 +858,7 @@ mod tests { test_multiple!( if_, compare_constants_equality: "if 1 == 2 { - + }", compare_constants_unequality: "if 1 != 1 { -- cgit v1.2.1