From 344f6a2d8ef2da81a58b7d6f6d1faf297a95ce14 Mon Sep 17 00:00:00 2001 From: Protryon Date: Fri, 12 Mar 2021 04:25:25 -0800 Subject: [PATCH 1/8] transparent keywords --- ast/src/common/input_keyword.rs | 9 +++++---- ast/src/common/mut_self_keyword.rs | 9 +++++---- ast/src/common/self_keyword.rs | 9 +++++---- ast/src/functions/input/input_variable.rs | 12 ++++++------ parser/src/parser/file.rs | 17 +++++++++++------ 5 files changed, 32 insertions(+), 24 deletions(-) diff --git a/ast/src/common/input_keyword.rs b/ast/src/common/input_keyword.rs index cc9d167861..e0cae2d4d5 100644 --- a/ast/src/common/input_keyword.rs +++ b/ast/src/common/input_keyword.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::{Node, Span}; +use crate::{Identifier, Node, Span}; use serde::{Deserialize, Serialize}; use std::fmt; @@ -22,8 +22,9 @@ use std::fmt; /// The `input` keyword can view program register, record, and state values. /// Values cannot be modified. The `input` keyword cannot be made mutable. #[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)] +#[serde(transparent)] pub struct InputKeyword { - pub span: Span, + pub ident: Identifier, } impl fmt::Display for InputKeyword { @@ -34,10 +35,10 @@ impl fmt::Display for InputKeyword { impl Node for InputKeyword { fn span(&self) -> &Span { - &self.span + &self.ident.span } fn set_span(&mut self, span: Span) { - self.span = span; + self.ident.span = span; } } diff --git a/ast/src/common/mut_self_keyword.rs b/ast/src/common/mut_self_keyword.rs index 34de7c9921..e5cb3f1d5b 100644 --- a/ast/src/common/mut_self_keyword.rs +++ b/ast/src/common/mut_self_keyword.rs @@ -14,15 +14,16 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::{Node, Span}; +use crate::{Identifier, Node, Span}; use serde::{Deserialize, Serialize}; use std::fmt; /// The `mut self` keyword can view and modify circuit values inside of a circuit function. #[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)] +#[serde(transparent)] pub struct MutSelfKeyword { - pub span: Span, + pub ident: Identifier, } impl fmt::Display for MutSelfKeyword { @@ -33,10 +34,10 @@ impl fmt::Display for MutSelfKeyword { impl Node for MutSelfKeyword { fn span(&self) -> &Span { - &self.span + &self.ident.span } fn set_span(&mut self, span: Span) { - self.span = span; + self.ident.span = span; } } diff --git a/ast/src/common/self_keyword.rs b/ast/src/common/self_keyword.rs index ba92db2160..5b80b97ac6 100644 --- a/ast/src/common/self_keyword.rs +++ b/ast/src/common/self_keyword.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::{Node, Span}; +use crate::{Identifier, Node, Span}; use serde::{Deserialize, Serialize}; use std::fmt; @@ -22,8 +22,9 @@ use std::fmt; /// The `self` keyword can view circuit values inside of a circuit function. /// Circuit values cannot be modified. To modify values use the `mut self` [MutSelfKeyword]. #[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)] +#[serde(transparent)] pub struct SelfKeyword { - pub span: Span, + pub ident: Identifier, } impl fmt::Display for SelfKeyword { @@ -34,10 +35,10 @@ impl fmt::Display for SelfKeyword { impl Node for SelfKeyword { fn span(&self) -> &Span { - &self.span + &self.ident.span } fn set_span(&mut self, span: Span) { - self.span = span; + self.ident.span = span; } } diff --git a/ast/src/functions/input/input_variable.rs b/ast/src/functions/input/input_variable.rs index f342cb3e1b..66116f4988 100644 --- a/ast/src/functions/input/input_variable.rs +++ b/ast/src/functions/input/input_variable.rs @@ -96,9 +96,9 @@ impl Node for FunctionInput { fn span(&self) -> &Span { use FunctionInput::*; match self { - InputKeyword(keyword) => &keyword.span, - SelfKeyword(keyword) => &keyword.span, - MutSelfKeyword(keyword) => &keyword.span, + InputKeyword(keyword) => &keyword.ident.span, + SelfKeyword(keyword) => &keyword.ident.span, + MutSelfKeyword(keyword) => &keyword.ident.span, Variable(variable) => &variable.span, } } @@ -106,9 +106,9 @@ impl Node for FunctionInput { fn set_span(&mut self, span: Span) { use FunctionInput::*; match self { - InputKeyword(keyword) => keyword.span = span, - SelfKeyword(keyword) => keyword.span = span, - MutSelfKeyword(keyword) => keyword.span = span, + InputKeyword(keyword) => keyword.ident.span = span, + SelfKeyword(keyword) => keyword.ident.span = span, + MutSelfKeyword(keyword) => keyword.ident.span = span, Variable(variable) => variable.span = span, } } diff --git a/parser/src/parser/file.rs b/parser/src/parser/file.rs index 36dca63852..4d19a782e8 100644 --- a/parser/src/parser/file.rs +++ b/parser/src/parser/file.rs @@ -309,11 +309,16 @@ impl ParserContext { /// pub fn parse_function_input(&mut self) -> SyntaxResult { if let Some(token) = self.eat(Token::Input) { - return Ok(FunctionInput::InputKeyword(InputKeyword { span: token.span })); + return Ok(FunctionInput::InputKeyword(InputKeyword { + ident: Identifier { + name: token.token.to_string(), + span: token.span, + }, + })); } let const_ = self.eat(Token::Const); let mutable = self.eat(Token::Mut); - let name = if let Some(token) = self.eat(Token::LittleSelf) { + let mut name = if let Some(token) = self.eat(Token::LittleSelf) { Identifier { name: token.token.to_string(), span: token.span, @@ -326,11 +331,11 @@ impl ParserContext { //error } if let Some(mutable) = &mutable { - return Ok(FunctionInput::MutSelfKeyword(MutSelfKeyword { - span: &mutable.span + &name.span, - })); + name.span = &mutable.span + &name.span; + name.name = "mut self".to_string(); + return Ok(FunctionInput::MutSelfKeyword(MutSelfKeyword { ident: name })); } - return Ok(FunctionInput::SelfKeyword(SelfKeyword { span: name.span })); + return Ok(FunctionInput::SelfKeyword(SelfKeyword { ident: name })); } self.expect(Token::Colon)?; let type_ = self.parse_type()?.0; From 0c72e3e26466dfcd0d0e182576e95b13b8b865be Mon Sep 17 00:00:00 2001 From: Protryon Date: Fri, 12 Mar 2021 10:40:05 -0800 Subject: [PATCH 2/8] ident -> identifier --- ast/src/common/input_keyword.rs | 6 +++--- ast/src/common/mut_self_keyword.rs | 6 +++--- ast/src/common/self_keyword.rs | 6 +++--- ast/src/functions/input/input_variable.rs | 12 ++++++------ parser/src/parser/expression.rs | 6 +++--- parser/src/parser/file.rs | 6 +++--- 6 files changed, 21 insertions(+), 21 deletions(-) diff --git a/ast/src/common/input_keyword.rs b/ast/src/common/input_keyword.rs index e0cae2d4d5..fecf89322e 100644 --- a/ast/src/common/input_keyword.rs +++ b/ast/src/common/input_keyword.rs @@ -24,7 +24,7 @@ use std::fmt; #[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)] #[serde(transparent)] pub struct InputKeyword { - pub ident: Identifier, + pub identifier: Identifier, } impl fmt::Display for InputKeyword { @@ -35,10 +35,10 @@ impl fmt::Display for InputKeyword { impl Node for InputKeyword { fn span(&self) -> &Span { - &self.ident.span + &self.identifier.span } fn set_span(&mut self, span: Span) { - self.ident.span = span; + self.identifier.span = span; } } diff --git a/ast/src/common/mut_self_keyword.rs b/ast/src/common/mut_self_keyword.rs index e5cb3f1d5b..d28c501be8 100644 --- a/ast/src/common/mut_self_keyword.rs +++ b/ast/src/common/mut_self_keyword.rs @@ -23,7 +23,7 @@ use std::fmt; #[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)] #[serde(transparent)] pub struct MutSelfKeyword { - pub ident: Identifier, + pub identifier: Identifier, } impl fmt::Display for MutSelfKeyword { @@ -34,10 +34,10 @@ impl fmt::Display for MutSelfKeyword { impl Node for MutSelfKeyword { fn span(&self) -> &Span { - &self.ident.span + &self.identifier.span } fn set_span(&mut self, span: Span) { - self.ident.span = span; + self.identifier.span = span; } } diff --git a/ast/src/common/self_keyword.rs b/ast/src/common/self_keyword.rs index 5b80b97ac6..06b6bb12a8 100644 --- a/ast/src/common/self_keyword.rs +++ b/ast/src/common/self_keyword.rs @@ -24,7 +24,7 @@ use std::fmt; #[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)] #[serde(transparent)] pub struct SelfKeyword { - pub ident: Identifier, + pub identifier: Identifier, } impl fmt::Display for SelfKeyword { @@ -35,10 +35,10 @@ impl fmt::Display for SelfKeyword { impl Node for SelfKeyword { fn span(&self) -> &Span { - &self.ident.span + &self.identifier.span } fn set_span(&mut self, span: Span) { - self.ident.span = span; + self.identifier.span = span; } } diff --git a/ast/src/functions/input/input_variable.rs b/ast/src/functions/input/input_variable.rs index 66116f4988..5ec9306aeb 100644 --- a/ast/src/functions/input/input_variable.rs +++ b/ast/src/functions/input/input_variable.rs @@ -96,9 +96,9 @@ impl Node for FunctionInput { fn span(&self) -> &Span { use FunctionInput::*; match self { - InputKeyword(keyword) => &keyword.ident.span, - SelfKeyword(keyword) => &keyword.ident.span, - MutSelfKeyword(keyword) => &keyword.ident.span, + InputKeyword(keyword) => &keyword.identifier.span, + SelfKeyword(keyword) => &keyword.identifier.span, + MutSelfKeyword(keyword) => &keyword.identifier.span, Variable(variable) => &variable.span, } } @@ -106,9 +106,9 @@ impl Node for FunctionInput { fn set_span(&mut self, span: Span) { use FunctionInput::*; match self { - InputKeyword(keyword) => keyword.ident.span = span, - SelfKeyword(keyword) => keyword.ident.span = span, - MutSelfKeyword(keyword) => keyword.ident.span = span, + InputKeyword(keyword) => keyword.identifier.span = span, + SelfKeyword(keyword) => keyword.identifier.span = span, + MutSelfKeyword(keyword) => keyword.identifier.span = span, Variable(variable) => variable.span = span, } } diff --git a/parser/src/parser/expression.rs b/parser/src/parser/expression.rs index ec4df7c2cd..f8dbac1f0e 100644 --- a/parser/src/parser/expression.rs +++ b/parser/src/parser/expression.rs @@ -507,7 +507,7 @@ impl ParserContext { /// Returns an [`Expression`] AST node if the next tokens represent an /// circuit initialization expression. /// - pub fn parse_circuit_init(&mut self, ident: Identifier) -> SyntaxResult { + pub fn parse_circuit_init(&mut self, identifier: Identifier) -> SyntaxResult { self.expect(Token::LeftCurly)?; let mut members = vec![]; let end_span; @@ -535,8 +535,8 @@ impl ParserContext { } } Ok(Expression::CircuitInit(CircuitInitExpression { - span: &ident.span + &end_span, - name: ident, + span: &identifier.span + &end_span, + name: identifier, members, })) } diff --git a/parser/src/parser/file.rs b/parser/src/parser/file.rs index 4d19a782e8..f61f228976 100644 --- a/parser/src/parser/file.rs +++ b/parser/src/parser/file.rs @@ -310,7 +310,7 @@ impl ParserContext { pub fn parse_function_input(&mut self) -> SyntaxResult { if let Some(token) = self.eat(Token::Input) { return Ok(FunctionInput::InputKeyword(InputKeyword { - ident: Identifier { + identifier: Identifier { name: token.token.to_string(), span: token.span, }, @@ -333,9 +333,9 @@ impl ParserContext { if let Some(mutable) = &mutable { name.span = &mutable.span + &name.span; name.name = "mut self".to_string(); - return Ok(FunctionInput::MutSelfKeyword(MutSelfKeyword { ident: name })); + return Ok(FunctionInput::MutSelfKeyword(MutSelfKeyword { identifier: name })); } - return Ok(FunctionInput::SelfKeyword(SelfKeyword { ident: name })); + return Ok(FunctionInput::SelfKeyword(SelfKeyword { identifier: name })); } self.expect(Token::Colon)?; let type_ = self.parse_type()?.0; From 0aa71ed3f92d7b8bfa02242f686c1ce8d08f15da Mon Sep 17 00:00:00 2001 From: Collin Chin Date: Fri, 12 Mar 2021 19:14:31 -0800 Subject: [PATCH 3/8] Add consty checks. Closes #749. --- asg/src/statement/iteration.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/asg/src/statement/iteration.rs b/asg/src/statement/iteration.rs index 26cfd2ba74..b13b1a6aae 100644 --- a/asg/src/statement/iteration.rs +++ b/asg/src/statement/iteration.rs @@ -57,6 +57,19 @@ impl<'a> FromAst<'a, leo_ast::IterationStatement> for &'a Statement<'a> { let expected_index_type = Some(PartialType::Integer(None, Some(IntegerType::U32))); let start = <&Expression<'a>>::from_ast(scope, &statement.start, expected_index_type.clone())?; let stop = <&Expression<'a>>::from_ast(scope, &statement.stop, expected_index_type)?; + + // Return an error if start or stop is not constant. + if !start.is_consty() { + return Err(AsgConvertError::unexpected_nonconst( + &start.span().cloned().unwrap_or_default(), + )); + } + if !stop.is_consty() { + return Err(AsgConvertError::unexpected_nonconst( + &stop.span().cloned().unwrap_or_default(), + )); + } + let variable = scope.alloc_variable(RefCell::new(InnerVariable { id: scope.context.get_id(), name: statement.variable.clone(), From 6ce003fd6ce66e36f83eb698b1cb3373364a9683 Mon Sep 17 00:00:00 2001 From: Collin Chin Date: Fri, 12 Mar 2021 20:35:34 -0800 Subject: [PATCH 4/8] fix program parsing formatted errors --- compiler/src/compiler.rs | 26 +++++++++++++++++++++++++- compiler/src/errors/compiler.rs | 4 ++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/compiler/src/compiler.rs b/compiler/src/compiler.rs index 20f44daa25..75170cf19c 100644 --- a/compiler/src/compiler.rs +++ b/compiler/src/compiler.rs @@ -224,7 +224,31 @@ impl<'a, F: PrimeField, G: GroupType> Compiler<'a, F, G> { let content = fs::read_to_string(&self.main_file_path) .map_err(|e| CompilerError::FileReadError(self.main_file_path.clone(), e))?; - self.parse_program_from_string(&content) + self.parse_program_from_string(&content).map_err(|mut error| { + // Return a formatted error with file path and code text. + + let path = match error.get_path().map(|x| x.to_string()) { + // Get the file path if it exists + Some(path) => path, + + // If a file path does not exist, then insert the main file path. + None => match self.main_file_path.clone().into_os_string().into_string() { + Err(e) => return CompilerError::FileStringError(e), + Ok(path) => path, + } + }; + + // Resolve the code text using the file path. + let content = match self.resolve_content(&path) { + Err(e) => return e, + Ok(x) => x, + }; + + // Update the formatted error. + error.set_path(&path, &content[..]); + + error + }) } /// diff --git a/compiler/src/errors/compiler.rs b/compiler/src/errors/compiler.rs index be76b88c7f..fce9cfef2d 100644 --- a/compiler/src/errors/compiler.rs +++ b/compiler/src/errors/compiler.rs @@ -24,6 +24,7 @@ use leo_state::LocalDataVerificationError; use bincode::Error as SerdeError; use std::path::PathBuf; +use std::ffi::OsString; #[derive(Debug, Error)] pub enum CompilerError { @@ -51,6 +52,9 @@ pub enum CompilerError { #[error("Cannot read from the provided file path '{:?}': {}", _0, _1)] FileReadError(PathBuf, std::io::Error), + #[error("Cannot parse file string `{:?}`", _0)] + FileStringError(OsString), + #[error("{}", _0)] LocalDataVerificationError(#[from] LocalDataVerificationError), From 712d2fbd0252246add02ee1ea822f04fd72beea4 Mon Sep 17 00:00:00 2001 From: Collin Chin Date: Fri, 12 Mar 2021 20:39:58 -0800 Subject: [PATCH 5/8] add test for non-constant loop ranges --- compiler/tests/statements/iteration_input.in | 2 ++ compiler/tests/statements/iteration_input.leo | 5 +++++ compiler/tests/statements/mod.rs | 11 ++++++++++- 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 compiler/tests/statements/iteration_input.in create mode 100644 compiler/tests/statements/iteration_input.leo diff --git a/compiler/tests/statements/iteration_input.in b/compiler/tests/statements/iteration_input.in new file mode 100644 index 0000000000..8d27f19dde --- /dev/null +++ b/compiler/tests/statements/iteration_input.in @@ -0,0 +1,2 @@ +[main] +x: u8 = 1; \ No newline at end of file diff --git a/compiler/tests/statements/iteration_input.leo b/compiler/tests/statements/iteration_input.leo new file mode 100644 index 0000000000..0ab62ab310 --- /dev/null +++ b/compiler/tests/statements/iteration_input.leo @@ -0,0 +1,5 @@ +function main(x: u8) { + for i in 0..x { + console.log("{}", i); + } +} \ No newline at end of file diff --git a/compiler/tests/statements/mod.rs b/compiler/tests/statements/mod.rs index 3aeb3f858b..f0a300ebc6 100644 --- a/compiler/tests/statements/mod.rs +++ b/compiler/tests/statements/mod.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -use crate::{assert_satisfied, expect_asg_error, generate_main_input, parse_program}; +use crate::{assert_satisfied, expect_asg_error, generate_main_input, parse_program, parse_program_with_input}; use leo_ast::InputValue; pub mod conditional; @@ -72,3 +72,12 @@ fn test_block() { assert_satisfied(program); } + +#[test] +fn test_iteration_input() { + let input_string = include_str!("iteration_input.in"); + let program_string = include_str!("iteration_input.leo"); + let error = parse_program_with_input(program_string, input_string).err().unwrap(); + + expect_asg_error(error) +} \ No newline at end of file From 45316e90d9f10d10c6b44667ebab2a3ca787f71a Mon Sep 17 00:00:00 2001 From: Collin Chin Date: Fri, 12 Mar 2021 21:02:38 -0800 Subject: [PATCH 6/8] formatting --- compiler/src/compiler.rs | 7 ++----- compiler/src/errors/compiler.rs | 3 +-- compiler/tests/statements/mod.rs | 4 ++-- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/compiler/src/compiler.rs b/compiler/src/compiler.rs index 75170cf19c..cb6d8aa123 100644 --- a/compiler/src/compiler.rs +++ b/compiler/src/compiler.rs @@ -19,10 +19,7 @@ use crate::{ constraints::{generate_constraints, generate_test_constraints}, errors::CompilerError, - CompilerOptions, - GroupType, - OutputBytes, - OutputFile, + CompilerOptions, GroupType, OutputBytes, OutputFile, }; use indexmap::IndexMap; pub use leo_asg::{new_context, AsgContext as Context, AsgContext}; @@ -235,7 +232,7 @@ impl<'a, F: PrimeField, G: GroupType> Compiler<'a, F, G> { None => match self.main_file_path.clone().into_os_string().into_string() { Err(e) => return CompilerError::FileStringError(e), Ok(path) => path, - } + }, }; // Resolve the code text using the file path. diff --git a/compiler/src/errors/compiler.rs b/compiler/src/errors/compiler.rs index fce9cfef2d..a9d13e6b24 100644 --- a/compiler/src/errors/compiler.rs +++ b/compiler/src/errors/compiler.rs @@ -23,8 +23,7 @@ use leo_parser::SyntaxError; use leo_state::LocalDataVerificationError; use bincode::Error as SerdeError; -use std::path::PathBuf; -use std::ffi::OsString; +use std::{ffi::OsString, path::PathBuf}; #[derive(Debug, Error)] pub enum CompilerError { diff --git a/compiler/tests/statements/mod.rs b/compiler/tests/statements/mod.rs index f0a300ebc6..aba9f62a5c 100644 --- a/compiler/tests/statements/mod.rs +++ b/compiler/tests/statements/mod.rs @@ -79,5 +79,5 @@ fn test_iteration_input() { let program_string = include_str!("iteration_input.leo"); let error = parse_program_with_input(program_string, input_string).err().unwrap(); - expect_asg_error(error) -} \ No newline at end of file + expect_asg_error(error); +} From 1c15fb5eff364ecbe1832ab063412974b08b3ea8 Mon Sep 17 00:00:00 2001 From: Collin Chin Date: Fri, 12 Mar 2021 21:13:17 -0800 Subject: [PATCH 7/8] formatting 2 --- compiler/src/compiler.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/compiler/src/compiler.rs b/compiler/src/compiler.rs index cb6d8aa123..4cb6692e27 100644 --- a/compiler/src/compiler.rs +++ b/compiler/src/compiler.rs @@ -19,7 +19,10 @@ use crate::{ constraints::{generate_constraints, generate_test_constraints}, errors::CompilerError, - CompilerOptions, GroupType, OutputBytes, OutputFile, + CompilerOptions, + GroupType, + OutputBytes, + OutputFile, }; use indexmap::IndexMap; pub use leo_asg::{new_context, AsgContext as Context, AsgContext}; From f1f8b99690d3c6fd0e2ebe0426a1e7f6b5566104 Mon Sep 17 00:00:00 2001 From: collin Date: Wed, 17 Mar 2021 12:35:16 -0700 Subject: [PATCH 8/8] add passing iteration test with loop variable --- compiler/tests/statements/iteration_variable.leo | 7 +++++++ compiler/tests/statements/mod.rs | 8 ++++++++ 2 files changed, 15 insertions(+) create mode 100644 compiler/tests/statements/iteration_variable.leo diff --git a/compiler/tests/statements/iteration_variable.leo b/compiler/tests/statements/iteration_variable.leo new file mode 100644 index 0000000000..d3d82b2664 --- /dev/null +++ b/compiler/tests/statements/iteration_variable.leo @@ -0,0 +1,7 @@ +function main() { + let x: u32 = 5; + + for i in 0..x { + console.log("{}", i); + } +} \ No newline at end of file diff --git a/compiler/tests/statements/mod.rs b/compiler/tests/statements/mod.rs index aba9f62a5c..8566d67576 100644 --- a/compiler/tests/statements/mod.rs +++ b/compiler/tests/statements/mod.rs @@ -81,3 +81,11 @@ fn test_iteration_input() { expect_asg_error(error); } + +#[test] +fn test_iteration_variable() { + let program_string = include_str!("iteration_variable.leo"); + let program = parse_program(program_string).unwrap(); + + assert_satisfied(program); +}