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;