diff --git a/asg/src/statement/iteration.rs b/asg/src/statement/iteration.rs index 756a8df33f..d5908d24da 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.context.alloc_variable(RefCell::new(InnerVariable { id: scope.context.get_id(), name: statement.variable.clone(), diff --git a/ast/src/common/input_keyword.rs b/ast/src/common/input_keyword.rs index cc9d167861..fecf89322e 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 identifier: 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.identifier.span } fn set_span(&mut self, span: Span) { - self.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 34de7c9921..d28c501be8 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 identifier: 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.identifier.span } fn set_span(&mut self, span: Span) { - self.span = span; + self.identifier.span = span; } } diff --git a/ast/src/common/self_keyword.rs b/ast/src/common/self_keyword.rs index ba92db2160..06b6bb12a8 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 identifier: 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.identifier.span } fn set_span(&mut self, span: Span) { - self.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 f342cb3e1b..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.span, - SelfKeyword(keyword) => &keyword.span, - MutSelfKeyword(keyword) => &keyword.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.span = span, - SelfKeyword(keyword) => keyword.span = span, - MutSelfKeyword(keyword) => keyword.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/compiler/src/compiler.rs b/compiler/src/compiler.rs index b2ff39b35a..d48fd71c28 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..a9d13e6b24 100644 --- a/compiler/src/errors/compiler.rs +++ b/compiler/src/errors/compiler.rs @@ -23,7 +23,7 @@ use leo_parser::SyntaxError; use leo_state::LocalDataVerificationError; use bincode::Error as SerdeError; -use std::path::PathBuf; +use std::{ffi::OsString, path::PathBuf}; #[derive(Debug, Error)] pub enum CompilerError { @@ -51,6 +51,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), 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/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 3aeb3f858b..8566d67576 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,20 @@ 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); +} + +#[test] +fn test_iteration_variable() { + let program_string = include_str!("iteration_variable.leo"); + let program = parse_program(program_string).unwrap(); + + assert_satisfied(program); +} 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 36dca63852..f61f228976 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 { + identifier: 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 { identifier: name })); } - return Ok(FunctionInput::SelfKeyword(SelfKeyword { span: name.span })); + return Ok(FunctionInput::SelfKeyword(SelfKeyword { identifier: name })); } self.expect(Token::Colon)?; let type_ = self.parse_type()?.0;