Merge branch 'master' into dead-code-elimination

This commit is contained in:
Max Bruce 2021-03-22 07:04:38 -07:00 committed by GitHub
commit d120e90d6e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 109 additions and 30 deletions

View File

@ -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 expected_index_type = Some(PartialType::Integer(None, Some(IntegerType::U32)));
let start = <&Expression<'a>>::from_ast(scope, &statement.start, expected_index_type.clone())?; 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)?; 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 { let variable = scope.context.alloc_variable(RefCell::new(InnerVariable {
id: scope.context.get_id(), id: scope.context.get_id(),
name: statement.variable.clone(), name: statement.variable.clone(),

View File

@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Node, Span}; use crate::{Identifier, Node, Span};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fmt; use std::fmt;
@ -22,8 +22,9 @@ use std::fmt;
/// The `input` keyword can view program register, record, and state values. /// The `input` keyword can view program register, record, and state values.
/// Values cannot be modified. The `input` keyword cannot be made mutable. /// Values cannot be modified. The `input` keyword cannot be made mutable.
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)] #[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)]
#[serde(transparent)]
pub struct InputKeyword { pub struct InputKeyword {
pub span: Span, pub identifier: Identifier,
} }
impl fmt::Display for InputKeyword { impl fmt::Display for InputKeyword {
@ -34,10 +35,10 @@ impl fmt::Display for InputKeyword {
impl Node for InputKeyword { impl Node for InputKeyword {
fn span(&self) -> &Span { fn span(&self) -> &Span {
&self.span &self.identifier.span
} }
fn set_span(&mut self, span: Span) { fn set_span(&mut self, span: Span) {
self.span = span; self.identifier.span = span;
} }
} }

View File

@ -14,15 +14,16 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Node, Span}; use crate::{Identifier, Node, Span};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fmt; use std::fmt;
/// The `mut self` keyword can view and modify circuit values inside of a circuit function. /// The `mut self` keyword can view and modify circuit values inside of a circuit function.
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)] #[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)]
#[serde(transparent)]
pub struct MutSelfKeyword { pub struct MutSelfKeyword {
pub span: Span, pub identifier: Identifier,
} }
impl fmt::Display for MutSelfKeyword { impl fmt::Display for MutSelfKeyword {
@ -33,10 +34,10 @@ impl fmt::Display for MutSelfKeyword {
impl Node for MutSelfKeyword { impl Node for MutSelfKeyword {
fn span(&self) -> &Span { fn span(&self) -> &Span {
&self.span &self.identifier.span
} }
fn set_span(&mut self, span: Span) { fn set_span(&mut self, span: Span) {
self.span = span; self.identifier.span = span;
} }
} }

View File

@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Node, Span}; use crate::{Identifier, Node, Span};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fmt; use std::fmt;
@ -22,8 +22,9 @@ use std::fmt;
/// The `self` keyword can view circuit values inside of a circuit function. /// 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]. /// Circuit values cannot be modified. To modify values use the `mut self` [MutSelfKeyword].
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)] #[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)]
#[serde(transparent)]
pub struct SelfKeyword { pub struct SelfKeyword {
pub span: Span, pub identifier: Identifier,
} }
impl fmt::Display for SelfKeyword { impl fmt::Display for SelfKeyword {
@ -34,10 +35,10 @@ impl fmt::Display for SelfKeyword {
impl Node for SelfKeyword { impl Node for SelfKeyword {
fn span(&self) -> &Span { fn span(&self) -> &Span {
&self.span &self.identifier.span
} }
fn set_span(&mut self, span: Span) { fn set_span(&mut self, span: Span) {
self.span = span; self.identifier.span = span;
} }
} }

View File

@ -96,9 +96,9 @@ impl Node for FunctionInput {
fn span(&self) -> &Span { fn span(&self) -> &Span {
use FunctionInput::*; use FunctionInput::*;
match self { match self {
InputKeyword(keyword) => &keyword.span, InputKeyword(keyword) => &keyword.identifier.span,
SelfKeyword(keyword) => &keyword.span, SelfKeyword(keyword) => &keyword.identifier.span,
MutSelfKeyword(keyword) => &keyword.span, MutSelfKeyword(keyword) => &keyword.identifier.span,
Variable(variable) => &variable.span, Variable(variable) => &variable.span,
} }
} }
@ -106,9 +106,9 @@ impl Node for FunctionInput {
fn set_span(&mut self, span: Span) { fn set_span(&mut self, span: Span) {
use FunctionInput::*; use FunctionInput::*;
match self { match self {
InputKeyword(keyword) => keyword.span = span, InputKeyword(keyword) => keyword.identifier.span = span,
SelfKeyword(keyword) => keyword.span = span, SelfKeyword(keyword) => keyword.identifier.span = span,
MutSelfKeyword(keyword) => keyword.span = span, MutSelfKeyword(keyword) => keyword.identifier.span = span,
Variable(variable) => variable.span = span, Variable(variable) => variable.span = span,
} }
} }

View File

@ -224,7 +224,31 @@ impl<'a, F: PrimeField, G: GroupType<F>> Compiler<'a, F, G> {
let content = fs::read_to_string(&self.main_file_path) let content = fs::read_to_string(&self.main_file_path)
.map_err(|e| CompilerError::FileReadError(self.main_file_path.clone(), e))?; .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
})
} }
/// ///

View File

@ -23,7 +23,7 @@ use leo_parser::SyntaxError;
use leo_state::LocalDataVerificationError; use leo_state::LocalDataVerificationError;
use bincode::Error as SerdeError; use bincode::Error as SerdeError;
use std::path::PathBuf; use std::{ffi::OsString, path::PathBuf};
#[derive(Debug, Error)] #[derive(Debug, Error)]
pub enum CompilerError { pub enum CompilerError {
@ -51,6 +51,9 @@ pub enum CompilerError {
#[error("Cannot read from the provided file path '{:?}': {}", _0, _1)] #[error("Cannot read from the provided file path '{:?}': {}", _0, _1)]
FileReadError(PathBuf, std::io::Error), FileReadError(PathBuf, std::io::Error),
#[error("Cannot parse file string `{:?}`", _0)]
FileStringError(OsString),
#[error("{}", _0)] #[error("{}", _0)]
LocalDataVerificationError(#[from] LocalDataVerificationError), LocalDataVerificationError(#[from] LocalDataVerificationError),

View File

@ -0,0 +1,2 @@
[main]
x: u8 = 1;

View File

@ -0,0 +1,5 @@
function main(x: u8) {
for i in 0..x {
console.log("{}", i);
}
}

View File

@ -0,0 +1,7 @@
function main() {
let x: u32 = 5;
for i in 0..x {
console.log("{}", i);
}
}

View File

@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>. // along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
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; use leo_ast::InputValue;
pub mod conditional; pub mod conditional;
@ -72,3 +72,20 @@ fn test_block() {
assert_satisfied(program); 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);
}

View File

@ -507,7 +507,7 @@ impl ParserContext {
/// Returns an [`Expression`] AST node if the next tokens represent an /// Returns an [`Expression`] AST node if the next tokens represent an
/// circuit initialization expression. /// circuit initialization expression.
/// ///
pub fn parse_circuit_init(&mut self, ident: Identifier) -> SyntaxResult<Expression> { pub fn parse_circuit_init(&mut self, identifier: Identifier) -> SyntaxResult<Expression> {
self.expect(Token::LeftCurly)?; self.expect(Token::LeftCurly)?;
let mut members = vec![]; let mut members = vec![];
let end_span; let end_span;
@ -535,8 +535,8 @@ impl ParserContext {
} }
} }
Ok(Expression::CircuitInit(CircuitInitExpression { Ok(Expression::CircuitInit(CircuitInitExpression {
span: &ident.span + &end_span, span: &identifier.span + &end_span,
name: ident, name: identifier,
members, members,
})) }))
} }

View File

@ -309,11 +309,16 @@ impl ParserContext {
/// ///
pub fn parse_function_input(&mut self) -> SyntaxResult<FunctionInput> { pub fn parse_function_input(&mut self) -> SyntaxResult<FunctionInput> {
if let Some(token) = self.eat(Token::Input) { 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 const_ = self.eat(Token::Const);
let mutable = self.eat(Token::Mut); 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 { Identifier {
name: token.token.to_string(), name: token.token.to_string(),
span: token.span, span: token.span,
@ -326,11 +331,11 @@ impl ParserContext {
//error //error
} }
if let Some(mutable) = &mutable { if let Some(mutable) = &mutable {
return Ok(FunctionInput::MutSelfKeyword(MutSelfKeyword { name.span = &mutable.span + &name.span;
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)?; self.expect(Token::Colon)?;
let type_ = self.parse_type()?.0; let type_ = self.parse_type()?.0;