Merge branch 'master' of https://github.com/AleoHQ/leo into feature/config-automatic

This commit is contained in:
raychu86 2020-09-03 00:21:33 -07:00
commit a3a121b42b
52 changed files with 616 additions and 91 deletions

View File

@ -14,7 +14,12 @@
// 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::{ast::Rule, common::Identifier, types::Type, SpanDef}; use crate::{
ast::Rule,
common::{Identifier, Mutable},
types::Type,
SpanDef,
};
use pest::Span; use pest::Span;
use pest_ast::FromPest; use pest_ast::FromPest;
@ -23,8 +28,9 @@ use serde::Serialize;
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] #[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
#[pest_ast(rule(Rule::circuit_variable_definition))] #[pest_ast(rule(Rule::circuit_variable_definition))]
pub struct CircuitVariableDefinition<'ast> { pub struct CircuitVariableDefinition<'ast> {
pub mutable: Option<Mutable>,
pub identifier: Identifier<'ast>, pub identifier: Identifier<'ast>,
pub _type: Type<'ast>, pub type_: Type<'ast>,
#[pest_ast(outer())] #[pest_ast(outer())]
#[serde(with = "SpanDef")] #[serde(with = "SpanDef")]
pub span: Span<'ast>, pub span: Span<'ast>,

View File

@ -38,6 +38,9 @@ pub use range::*;
pub mod range_or_expression; pub mod range_or_expression;
pub use range_or_expression::*; pub use range_or_expression::*;
pub mod self_keyword;
pub use self_keyword::*;
pub mod spread; pub mod spread;
pub use spread::*; pub use spread::*;

View File

@ -0,0 +1,34 @@
// Copyright (C) 2019-2020 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// 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/>.
use crate::{
ast::{span_into_string, Rule},
SpanDef,
};
use pest::Span;
use pest_ast::FromPest;
use serde::Serialize;
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
#[pest_ast(rule(Rule::self_keyword))]
pub struct SelfKeyword<'ast> {
#[pest_ast(outer(with(span_into_string)))]
pub keyword: String,
#[pest_ast(outer())]
#[serde(with = "SpanDef")]
pub span: Span<'ast>,
}

View File

@ -1,3 +1,19 @@
// Copyright (C) 2019-2020 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// 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/>.
use crate::{ast::Rule, expressions::Expression, SpanDef}; use crate::{ast::Rule, expressions::Expression, SpanDef};
use pest::Span; use pest::Span;

View File

@ -1,3 +1,19 @@
// Copyright (C) 2019-2020 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// 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/>.
use crate::{ast::Rule, console::FormattedString, SpanDef}; use crate::{ast::Rule, console::FormattedString, SpanDef};
use pest::Span; use pest::Span;

View File

@ -1,3 +1,19 @@
// Copyright (C) 2019-2020 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// 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/>.
use crate::{ use crate::{
ast::Rule, ast::Rule,
console::{ConsoleAssert, ConsoleDebug, ConsoleError, ConsoleLog}, console::{ConsoleAssert, ConsoleDebug, ConsoleError, ConsoleLog},

View File

@ -1,3 +1,19 @@
// Copyright (C) 2019-2020 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// 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/>.
use crate::{ use crate::{
ast::Rule, ast::Rule,
common::LineEnd, common::LineEnd,

View File

@ -1,3 +1,19 @@
// Copyright (C) 2019-2020 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// 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/>.
pub mod console_assert; pub mod console_assert;
pub use console_assert::*; pub use console_assert::*;

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::{ast::Rule, circuits::CircuitVariable, common::Identifier, SpanDef}; use crate::{ast::Rule, circuits::CircuitVariable, common::Identifier, types::SelfType, SpanDef};
use pest::Span; use pest::Span;
use pest_ast::FromPest; use pest_ast::FromPest;
@ -23,9 +23,16 @@ use serde::Serialize;
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] #[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
#[pest_ast(rule(Rule::expression_circuit_inline))] #[pest_ast(rule(Rule::expression_circuit_inline))]
pub struct CircuitInlineExpression<'ast> { pub struct CircuitInlineExpression<'ast> {
pub identifier: Identifier<'ast>, pub name: CircuitName<'ast>,
pub members: Vec<CircuitVariable<'ast>>, pub members: Vec<CircuitVariable<'ast>>,
#[pest_ast(outer())] #[pest_ast(outer())]
#[serde(with = "SpanDef")] #[serde(with = "SpanDef")]
pub span: Span<'ast>, pub span: Span<'ast>,
} }
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
#[pest_ast(rule(Rule::circuit_name))]
pub enum CircuitName<'ast> {
SelfType(SelfType<'ast>),
Identifier(Identifier<'ast>),
}

View File

@ -14,7 +14,13 @@
// 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::{access::Access, ast::Rule, common::Identifier, SpanDef}; use crate::{
access::Access,
ast::Rule,
common::{Identifier, SelfKeyword},
functions::InputKeyword,
SpanDef,
};
use pest::Span; use pest::Span;
use pest_ast::FromPest; use pest_ast::FromPest;
@ -23,9 +29,17 @@ use serde::Serialize;
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] #[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
#[pest_ast(rule(Rule::expression_postfix))] #[pest_ast(rule(Rule::expression_postfix))]
pub struct PostfixExpression<'ast> { pub struct PostfixExpression<'ast> {
pub identifier: Identifier<'ast>, pub name: KeywordOrIdentifier<'ast>,
pub accesses: Vec<Access<'ast>>, pub accesses: Vec<Access<'ast>>,
#[pest_ast(outer())] #[pest_ast(outer())]
#[serde(with = "SpanDef")] #[serde(with = "SpanDef")]
pub span: Span<'ast>, pub span: Span<'ast>,
} }
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
#[pest_ast(rule(Rule::keyword_or_identifier))]
pub enum KeywordOrIdentifier<'ast> {
SelfKeyword(SelfKeyword<'ast>),
Input(InputKeyword<'ast>),
Identifier(Identifier<'ast>),
}

View File

@ -30,7 +30,7 @@ use serde::Serialize;
pub struct FunctionInput<'ast> { pub struct FunctionInput<'ast> {
pub mutable: Option<Mutable>, pub mutable: Option<Mutable>,
pub identifier: Identifier<'ast>, pub identifier: Identifier<'ast>,
pub _type: Type<'ast>, pub type_: Type<'ast>,
#[pest_ast(outer())] #[pest_ast(outer())]
#[serde(with = "SpanDef")] #[serde(with = "SpanDef")]
pub span: Span<'ast>, pub span: Span<'ast>,

View File

@ -21,29 +21,32 @@ definition_annotated = { annotation ~ NEWLINE* ~ definition}
// Declared in common/identifier.rs // Declared in common/identifier.rs
identifier = @{ ((!protected_name ~ ASCII_ALPHA) | (protected_name ~ (ASCII_ALPHANUMERIC | "_"))) ~ (ASCII_ALPHANUMERIC | "_")* } identifier = @{ ((!protected_name ~ ASCII_ALPHA) | (protected_name ~ (ASCII_ALPHANUMERIC | "_"))) ~ (ASCII_ALPHANUMERIC | "_")* }
protected_name = { protected_name = {
"address" "as"
| "as"
| "circuit" | "circuit"
| "const" | "const"
| "console" | "console"
| "else" | "else"
| "false"
| "field"
| "for" | "for"
| "function" | "function"
| "group"
| "if" | "if"
| "import" | "import"
| input_keyword
| "in" | "in"
| "let" | "let"
| "mut" | "mut"
| "return" | "return"
| self_keyword
| "static" | "static"
| "string" | "string"
| "test" | "test"
| "true" | type_data
| type_self
| value_boolean
} }
// Declared in common/self_keyword.rs
self_keyword = { "self" }
// Declared in common/line_end.rs // Declared in common/line_end.rs
LINE_END = { ";" ~ NEWLINE* } LINE_END = { ";" ~ NEWLINE* }
@ -311,7 +314,7 @@ circuit = { "circuit " ~ identifier ~ "{" ~ NEWLINE* ~ circuit_member* ~ NEWLINE
circuit_variable = { identifier ~ ":" ~ expression } circuit_variable = { identifier ~ ":" ~ expression }
// Declared in circuits/circuit_variable_definition.rs // Declared in circuits/circuit_variable_definition.rs
circuit_variable_definition = { identifier ~ ":" ~ type_ ~ ","?} circuit_variable_definition = { mutable? ~ identifier ~ ":" ~ type_ ~ ","?}
// Declared in circuits/circuit_function.rs // Declared in circuits/circuit_function.rs
circuit_function = { static_? ~ function } circuit_function = { static_? ~ function }
@ -353,14 +356,29 @@ expression_array_inline = { "[" ~ NEWLINE* ~ inline_array_inner ~ NEWLINE* ~ "]"
inline_array_inner = _{(spread_or_expression ~ ("," ~ NEWLINE* ~ spread_or_expression)*)?} inline_array_inner = _{(spread_or_expression ~ ("," ~ NEWLINE* ~ spread_or_expression)*)?}
// Declared in expressions/circuit_inline_expression.rs // Declared in expressions/circuit_inline_expression.rs
expression_circuit_inline = { identifier ~ "{" ~ NEWLINE* ~ circuit_variable_list ~ NEWLINE* ~ "}" } expression_circuit_inline = { circuit_name ~ "{" ~ NEWLINE* ~ circuit_variable_list ~ NEWLINE* ~ "}" }
// Declared in expressions/circuit_inline_expression.rs
circuit_name = {
type_self
| identifier
}
// Declared in expressions/circuit_inline_expression.rs
circuit_variable_list = _{ (circuit_variable ~ ("," ~ NEWLINE* ~ circuit_variable)*)? ~ ","? } circuit_variable_list = _{ (circuit_variable ~ ("," ~ NEWLINE* ~ circuit_variable)*)? ~ ","? }
// Declared in expressions/unary_expression.rs // Declared in expressions/unary_expression.rs
expression_unary = { operation_unary ~ expression_term } expression_unary = { operation_unary ~ expression_term }
// Declared in expressions/postfix_expression.rs // Declared in expressions/postfix_expression.rs
expression_postfix = ${ identifier ~ access+ } expression_postfix = ${ keyword_or_identifier ~ access+ }
// Declared in expressions/postfix_expression.rs
keyword_or_identifier = {
input_keyword
| self_keyword
| identifier
}
/// Statements /// Statements
@ -412,8 +430,8 @@ input_keyword = { "input" }
// Declared in functions/input/input.rs // Declared in functions/input/input.rs
input = { input = {
function_input input_keyword
| input_keyword | function_input
} }
input_tuple = _{ "(" ~ NEWLINE* ~ (input ~ ("," ~ NEWLINE* ~ input)* ~ ","?)? ~ NEWLINE* ~ ")"} input_tuple = _{ "(" ~ NEWLINE* ~ (input ~ ("," ~ NEWLINE* ~ input)* ~ ","?)? ~ NEWLINE* ~ ")"}

View File

@ -25,5 +25,5 @@ pub enum ArrayElement<'ast> {
Basic(DataType), Basic(DataType),
Tuple(TupleType<'ast>), Tuple(TupleType<'ast>),
Circuit(CircuitType<'ast>), Circuit(CircuitType<'ast>),
SelfType(SelfType), SelfType(SelfType<'ast>),
} }

View File

@ -14,11 +14,21 @@
// 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::ast::Rule; use crate::{
ast::{span_into_string, Rule},
SpanDef,
};
use pest::Span;
use pest_ast::FromPest; use pest_ast::FromPest;
use serde::Serialize; use serde::Serialize;
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)] #[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
#[pest_ast(rule(Rule::type_self))] #[pest_ast(rule(Rule::type_self))]
pub struct SelfType {} pub struct SelfType<'ast> {
#[pest_ast(outer(with(span_into_string)))]
pub keyword: String,
#[pest_ast(outer())]
#[serde(with = "SpanDef")]
pub span: Span<'ast>,
}

View File

@ -27,7 +27,7 @@ pub enum Type<'ast> {
Array(ArrayType<'ast>), Array(ArrayType<'ast>),
Tuple(TupleType<'ast>), Tuple(TupleType<'ast>),
Circuit(CircuitType<'ast>), Circuit(CircuitType<'ast>),
SelfType(SelfType), SelfType(SelfType<'ast>),
} }
impl<'ast> fmt::Display for Type<'ast> { impl<'ast> fmt::Display for Type<'ast> {
@ -37,7 +37,7 @@ impl<'ast> fmt::Display for Type<'ast> {
Type::Array(ref _type) => write!(f, "array"), Type::Array(ref _type) => write!(f, "array"),
Type::Tuple(ref _type) => write!(f, "tuple"), Type::Tuple(ref _type) => write!(f, "tuple"),
Type::Circuit(ref _type) => write!(f, "struct"), Type::Circuit(ref _type) => write!(f, "struct"),
Type::SelfType(ref _type) => write!(f, "Self"), Type::SelfType(ref type_) => write!(f, "{}", type_.keyword),
} }
} }
} }

View File

@ -1,3 +1,19 @@
// Copyright (C) 2019-2020 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// 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/>.
//! Enforces an assert equals statement in a compiled Leo program. //! Enforces an assert equals statement in a compiled Leo program.
use crate::{errors::ConsoleError, program::ConstrainedProgram, value::ConstrainedValue, GroupType}; use crate::{errors::ConsoleError, program::ConstrainedProgram, value::ConstrainedValue, GroupType};

View File

@ -1,3 +1,19 @@
// Copyright (C) 2019-2020 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// 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/>.
//! Evaluates a macro in a compiled Leo program. //! Evaluates a macro in a compiled Leo program.
use crate::{errors::ConsoleError, program::ConstrainedProgram, GroupType}; use crate::{errors::ConsoleError, program::ConstrainedProgram, GroupType};

View File

@ -1,3 +1,19 @@
// Copyright (C) 2019-2020 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// 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/>.
pub mod assert; pub mod assert;
pub use assert::*; pub use assert::*;

View File

@ -1,3 +1,19 @@
// Copyright (C) 2019-2020 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// 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/>.
use crate::errors::ExpressionError; use crate::errors::ExpressionError;
use leo_typed::{Error as FormattedError, Span}; use leo_typed::{Error as FormattedError, Span};

View File

@ -96,6 +96,12 @@ impl StatementError {
Self::new_from_span(message, span) Self::new_from_span(message, span)
} }
pub fn immutable_circuit_variable(name: String, span: Span) -> Self {
let message = format!("Circuit member variable `{}` is immutable", name);
Self::new_from_span(message, span)
}
pub fn indicator_calculation(name: String, span: Span) -> Self { pub fn indicator_calculation(name: String, span: Span) -> Self {
let message = format!( let message = format!(
"Constraint system failed to evaluate branch selection indicator `{}`", "Constraint system failed to evaluate branch selection indicator `{}`",
@ -168,8 +174,8 @@ impl StatementError {
Self::new_from_span(message, span) Self::new_from_span(message, span)
} }
pub fn undefined_circuit_object(name: String, span: Span) -> Self { pub fn undefined_circuit_variable(name: String, span: Span) -> Self {
let message = format!("Attempted to assign to unknown circuit object `{}`", name); let message = format!("Attempted to assign to unknown circuit member variable `{}`", name);
Self::new_from_span(message, span) Self::new_from_span(message, span)
} }

View File

@ -77,9 +77,9 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
for stored_member in members { for stored_member in members {
let circuit_scope = new_scope(file_scope.clone(), circuit_name.to_string()); let circuit_scope = new_scope(file_scope.clone(), circuit_name.to_string());
let self_keyword = new_scope(circuit_scope, SELF_KEYWORD.to_string()); let self_keyword = new_scope(circuit_scope, SELF_KEYWORD.to_string());
let field = new_scope(self_keyword, stored_member.0.to_string()); let variable = new_scope(self_keyword, stored_member.0.to_string());
self.store(field, stored_member.1.clone()); self.store(variable, stored_member.1.clone());
} }
} }
ConstrainedValue::Static(value) => { ConstrainedValue::Static(value) => {

View File

@ -55,22 +55,27 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
for member in circuit.members.clone().into_iter() { for member in circuit.members.clone().into_iter() {
match member { match member {
CircuitMember::CircuitVariable(identifier, _type) => { CircuitMember::CircuitVariable(is_mutable, identifier, type_) => {
let matched_variable = members let matched_variable = members
.clone() .clone()
.into_iter() .into_iter()
.find(|variable| variable.identifier.eq(&identifier)); .find(|variable| variable.identifier.eq(&identifier));
match matched_variable { match matched_variable {
Some(variable) => { Some(variable) => {
// Resolve and enforce circuit object // Resolve and enforce circuit variable
let variable_value = self.enforce_expression( let mut variable_value = self.enforce_expression(
cs, cs,
file_scope.clone(), file_scope.clone(),
function_scope.clone(), function_scope.clone(),
Some(_type.clone()), Some(type_.clone()),
variable.expression, variable.expression,
)?; )?;
// Add mutability to circuit variable
if is_mutable {
variable_value = ConstrainedValue::Mutable(Box::new(variable_value))
}
resolved_members.push(ConstrainedCircuitMember(identifier, variable_value)) resolved_members.push(ConstrainedCircuitMember(identifier, variable_value))
} }
None => return Err(ExpressionError::expected_circuit_member(identifier.to_string(), span)), None => return Err(ExpressionError::expected_circuit_member(identifier.to_string(), span)),

View File

@ -33,19 +33,20 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
cs: &mut CS, cs: &mut CS,
indicator: Option<Boolean>, indicator: Option<Boolean>,
circuit_name: String, circuit_name: String,
object_name: Identifier, variable_name: Identifier,
mut new_value: ConstrainedValue<F, G>, mut new_value: ConstrainedValue<F, G>,
span: Span, span: Span,
) -> Result<(), StatementError> { ) -> Result<(), StatementError> {
let condition = indicator.unwrap_or(Boolean::Constant(true)); let condition = indicator.unwrap_or(Boolean::Constant(true));
// Get the mutable circuit by name
match self.get_mutable_assignee(circuit_name, span.clone())? { match self.get_mutable_assignee(circuit_name, span.clone())? {
ConstrainedValue::CircuitExpression(_variable, members) => { ConstrainedValue::CircuitExpression(_variable, members) => {
// Modify the circuit variable in place // Modify the circuit variable in place
let matched_variable = members.into_iter().find(|object| object.0 == object_name); let matched_variable = members.into_iter().find(|member| member.0 == variable_name);
match matched_variable { match matched_variable {
Some(object) => match &object.1 { Some(member) => match &member.1 {
ConstrainedValue::Function(_circuit_identifier, function) => { ConstrainedValue::Function(_circuit_identifier, function) => {
return Err(StatementError::immutable_circuit_function( return Err(StatementError::immutable_circuit_function(
function.identifier.to_string(), function.identifier.to_string(),
@ -55,27 +56,35 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
ConstrainedValue::Static(_value) => { ConstrainedValue::Static(_value) => {
return Err(StatementError::immutable_circuit_function("static".into(), span)); return Err(StatementError::immutable_circuit_function("static".into(), span));
} }
_ => { ConstrainedValue::Mutable(value) => {
new_value.resolve_type(Some(object.1.to_type(span.clone())?), span.clone())?; new_value.resolve_type(Some(value.to_type(span.clone())?), span.clone())?;
let name_unique = format!("select {} {}:{}", new_value, span.line, span.start); let name_unique = format!("select {} {}:{}", new_value, span.line, span.start);
let selected_value = ConstrainedValue::conditionally_select( let selected_value = ConstrainedValue::conditionally_select(
cs.ns(|| name_unique), cs.ns(|| name_unique),
&condition, &condition,
&new_value, &new_value,
&object.1, &member.1,
) )
.map_err(|_| { .map_err(|_| {
StatementError::select_fail(new_value.to_string(), object.1.to_string(), span) StatementError::select_fail(new_value.to_string(), member.1.to_string(), span)
})?; })?;
object.1 = selected_value.to_owned(); member.1 = selected_value.to_owned();
}
_ => {
return Err(StatementError::immutable_circuit_variable(variable_name.name, span));
} }
}, },
None => return Err(StatementError::undefined_circuit_object(object_name.to_string(), span)), None => {
return Err(StatementError::undefined_circuit_variable(
variable_name.to_string(),
span,
));
}
} }
} }
_ => return Err(StatementError::undefined_circuit(object_name.to_string(), span)), _ => return Err(StatementError::undefined_circuit(variable_name.to_string(), span)),
} }
Ok(()) Ok(())

View File

@ -132,6 +132,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedValue<F, G> {
Type::Tuple(types) Type::Tuple(types)
} }
ConstrainedValue::CircuitExpression(id, _members) => Type::Circuit(id.clone()), ConstrainedValue::CircuitExpression(id, _members) => Type::Circuit(id.clone()),
ConstrainedValue::Mutable(value) => return value.to_type(span),
value => return Err(ValueError::implicit(value.to_string(), span)), value => return Err(ValueError::implicit(value.to_string(), span)),
}) })
} }

View File

@ -18,7 +18,6 @@ use crate::{
assert_satisfied, assert_satisfied,
expect_compiler_error, expect_compiler_error,
get_output, get_output,
integers::{expect_computation_error, expect_parsing_error},
parse_program, parse_program,
parse_program_with_input, parse_program_with_input,
EdwardsTestCompiler, EdwardsTestCompiler,

View File

@ -19,9 +19,9 @@ circuit PedersenHash {
function main() { function main() {
let parameters = [0u32; 512]; let parameters = [0u32; 512];
let pedersen = PedersenHash::new(parameters); let pedersen = PedersenHash::new(parameters);
let input: [bool; 512] = [true; 512]; let hash_input: [bool; 512] = [true; 512];
let res = pedersen.hash(input); let res = pedersen.hash(hash_input);
console.assert(res == 0u32); console.assert(res == 0u32);
} }

View File

@ -1,3 +1,19 @@
// Copyright (C) 2019-2020 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// 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/>.
use crate::{assert_satisfied, expect_compiler_error, generate_main_input, parse_program}; use crate::{assert_satisfied, expect_compiler_error, generate_main_input, parse_program};
use leo_typed::InputValue; use leo_typed::InputValue;

View File

@ -0,0 +1,9 @@
// Adding the `mut` keyword makes a circuit variable mutable.
circuit Foo {
function bar() {}
}
function main() {
let mut a = Foo { x: 1 };
a.bar = 0;
}

View File

@ -0,0 +1,9 @@
// Adding the `mut` keyword makes a circuit variable mutable.
circuit Foo {
static function bar() {}
}
function main() {
let mut a = Foo { x: 1 };
a.bar = 0;
}

View File

@ -0,0 +1,11 @@
// Adding the `mut` keyword makes a circuit variable mutable.
circuit Foo {
mut x: u32
}
function main() {
let mut a = Foo { x: 1 };
a.x = 0;
console.assert(a.x == 0u32);
}

View File

@ -78,9 +78,33 @@ fn test_circuit_mut() {
let bytes = include_bytes!("circuit_mut.leo"); let bytes = include_bytes!("circuit_mut.leo");
let program = parse_program(bytes).unwrap(); let program = parse_program(bytes).unwrap();
expect_compiler_error(program);
}
#[test]
fn test_circuit_variable_mut() {
let bytes = include_bytes!("circuit_variable_mut.leo");
let program = parse_program(bytes).unwrap();
assert_satisfied(program); assert_satisfied(program);
} }
#[test]
fn test_circuit_function_mut() {
let bytes = include_bytes!("circuit_function_mut.leo");
let program = parse_program(bytes).unwrap();
expect_compiler_error(program);
}
#[test]
fn test_circuit_static_function_mut() {
let bytes = include_bytes!("circuit_static_function_mut.leo");
let program = parse_program(bytes).unwrap();
expect_compiler_error(program);
}
#[test] #[test]
fn test_function_input() { fn test_function_input() {
let bytes = include_bytes!("function_input.leo"); let bytes = include_bytes!("function_input.leo");

View File

@ -0,0 +1,3 @@
function main() {
let address = 0u32;
}

View File

@ -0,0 +1,3 @@
function main() {
let console = 0u32;
}

View File

@ -0,0 +1,3 @@
function main() {
let field = 0u32;
}

View File

@ -0,0 +1,3 @@
function main() {
let group = 0u32;
}

View File

@ -0,0 +1,3 @@
function main() {
let i8 = 0u32;
}

View File

@ -0,0 +1,3 @@
function main() {
let input = 0u32;
}

View File

@ -0,0 +1,97 @@
// Copyright (C) 2019-2020 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// 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/>.
use crate::parse_program;
#[test]
fn test_address_name_fail() {
let bytes = include_bytes!("address_fail.leo");
let syntax_error = parse_program(bytes).is_err();
assert!(syntax_error);
}
#[test]
fn test_console_name_fail() {
let bytes = include_bytes!("console_fail.leo");
let syntax_error = parse_program(bytes).is_err();
assert!(syntax_error);
}
#[test]
fn test_field_name_fail() {
let bytes = include_bytes!("field_fail.leo");
let syntax_error = parse_program(bytes).is_err();
assert!(syntax_error);
}
#[test]
fn test_group_name_fail() {
let bytes = include_bytes!("group_fail.leo");
let syntax_error = parse_program(bytes).is_err();
assert!(syntax_error);
}
#[test]
fn test_i8_name_fail() {
let bytes = include_bytes!("i8_fail.leo");
let syntax_error = parse_program(bytes).is_err();
assert!(syntax_error);
}
#[test]
fn test_input_name_fail() {
let bytes = include_bytes!("input_fail.leo");
let syntax_error = parse_program(bytes).is_err();
assert!(syntax_error);
}
#[test]
fn test_self_type_name_fail() {
let bytes = include_bytes!("self_type_fail.leo");
let syntax_error = parse_program(bytes).is_err();
assert!(syntax_error);
}
#[test]
fn test_self_keyword_name_fail() {
let bytes = include_bytes!("self_keyword_fail.leo");
let syntax_error = parse_program(bytes).is_err();
assert!(syntax_error);
}
#[test]
fn test_true_name_fail() {
let bytes = include_bytes!("true_fail.leo");
let syntax_error = parse_program(bytes).is_err();
assert!(syntax_error);
}
#[test]
fn test_u8_name_fail() {
let bytes = include_bytes!("u8_fail.leo");
let syntax_error = parse_program(bytes).is_err();
assert!(syntax_error);
}

View File

@ -0,0 +1,3 @@
function main() {
let Self = 0u32;
}

View File

@ -0,0 +1,3 @@
function main() {
let Self = 0u32;
}

View File

@ -0,0 +1,3 @@
function main() {
let address = 0u32;
}

View File

@ -0,0 +1,3 @@
function main() {
let u8 = 0u32;
}

View File

@ -19,6 +19,8 @@ use leo_ast::ParserError;
use leo_compiler::errors::{CompilerError, ExpressionError, FunctionError, StatementError}; use leo_compiler::errors::{CompilerError, ExpressionError, FunctionError, StatementError};
use leo_input::InputParserError; use leo_input::InputParserError;
pub mod identifiers;
#[test] #[test]
#[ignore] #[ignore]
fn test_semicolon() { fn test_semicolon() {

View File

@ -21,6 +21,6 @@ circuit PedersenHash {
function main() -> group { function main() -> group {
const parameters = [1group; 256]; const parameters = [1group; 256];
const pedersen = PedersenHash::new(parameters); const pedersen = PedersenHash::new(parameters);
let input: [bool; 256] = [true; 256]; let hash_input: [bool; 256] = [true; 256];
return pedersen.hash(input) return pedersen.hash(hash_input)
} }

View File

@ -26,15 +26,18 @@ use std::fmt;
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum CircuitMember { pub enum CircuitMember {
CircuitVariable(Identifier, Type), // (is_mutable, variable_name, variable_type)
CircuitVariable(bool, Identifier, Type),
// (is_static, function)
CircuitFunction(bool, Function), CircuitFunction(bool, Function),
} }
impl<'ast> From<AstCircuitVariableDefinition<'ast>> for CircuitMember { impl<'ast> From<AstCircuitVariableDefinition<'ast>> for CircuitMember {
fn from(circuit_value: AstCircuitVariableDefinition<'ast>) -> Self { fn from(circuit_value: AstCircuitVariableDefinition<'ast>) -> Self {
CircuitMember::CircuitVariable( CircuitMember::CircuitVariable(
circuit_value.mutable.is_some(),
Identifier::from(circuit_value.identifier), Identifier::from(circuit_value.identifier),
Type::from(circuit_value._type), Type::from(circuit_value.type_),
) )
} }
} }
@ -60,9 +63,14 @@ impl<'ast> From<AstCircuitMember<'ast>> for CircuitMember {
impl fmt::Display for CircuitMember { impl fmt::Display for CircuitMember {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { match self {
CircuitMember::CircuitVariable(ref identifier, ref _type) => write!(f, "{}: {}", identifier, _type), CircuitMember::CircuitVariable(ref mutable, ref identifier, ref type_) => {
CircuitMember::CircuitFunction(ref _static, ref function) => { if *mutable {
if *_static { write!(f, "mut ")?;
}
write!(f, "{}: {}", identifier, type_)
}
CircuitMember::CircuitFunction(ref static_, ref function) => {
if *static_ {
write!(f, "static ")?; write!(f, "static ")?;
} }
write!(f, "{}", function) write!(f, "{}", function)

View File

@ -22,6 +22,12 @@ use leo_ast::{
}; };
use leo_input::common::Identifier as InputAstIdentifier; use leo_input::common::Identifier as InputAstIdentifier;
use leo_ast::{
common::SelfKeyword,
expressions::{CircuitName, KeywordOrIdentifier},
functions::InputKeyword,
types::SelfType,
};
use serde::{ use serde::{
de::{self, Visitor}, de::{self, Visitor},
Deserialize, Deserialize,
@ -84,6 +90,52 @@ impl<'ast> From<AnnotationArgument<'ast>> for Identifier {
} }
} }
impl<'ast> From<KeywordOrIdentifier<'ast>> for Identifier {
fn from(name: KeywordOrIdentifier<'ast>) -> Self {
match name {
KeywordOrIdentifier::SelfKeyword(keyword) => Identifier::from(keyword),
KeywordOrIdentifier::Input(keyword) => Identifier::from(keyword),
KeywordOrIdentifier::Identifier(identifier) => Identifier::from(identifier),
}
}
}
impl<'ast> From<SelfKeyword<'ast>> for Identifier {
fn from(self_: SelfKeyword<'ast>) -> Self {
Self {
name: self_.keyword,
span: Span::from(self_.span),
}
}
}
impl<'ast> From<InputKeyword<'ast>> for Identifier {
fn from(input: InputKeyword<'ast>) -> Self {
Self {
name: input.keyword,
span: Span::from(input.span),
}
}
}
impl<'ast> From<CircuitName<'ast>> for Identifier {
fn from(name: CircuitName<'ast>) -> Self {
match name {
CircuitName::SelfType(self_type) => Identifier::from(self_type),
CircuitName::Identifier(identifier) => Identifier::from(identifier),
}
}
}
impl<'ast> From<SelfType<'ast>> for Identifier {
fn from(self_type: SelfType<'ast>) -> Self {
Self {
name: self_type.keyword,
span: Span::from(self_type.span),
}
}
}
impl fmt::Display for Identifier { impl fmt::Display for Identifier {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.name) write!(f, "{}", self.name)

View File

@ -45,40 +45,3 @@ impl<'ast> From<AstSpan<'ast>> for Span {
} }
} }
} }
pub fn find_line_start(pos: &Position) -> usize {
let input = pos.line_of();
if input.is_empty() {
return 0;
};
// Position's pos is always a UTF-8 border.
let start = input
.char_indices()
.rev()
.skip_while(|&(i, _)| i >= pos.pos())
.find(|&(_, c)| c == '\n');
match start {
Some((i, _)) => i,
None => 0,
}
}
pub fn find_line_end(pos: &Position) -> usize {
let input = pos.line_of();
if input.is_empty() {
0
} else if pos.pos() == input.len() - 1 {
input.len()
} else {
// Position's pos is always a UTF-8 border.
let end = input
.char_indices()
.skip_while(|&(i, _)| i < pos.pos())
.find(|&(_, c)| c == '\n');
match end {
Some((i, _)) => i,
None => input.len(),
}
}
}

View File

@ -1,3 +1,19 @@
// Copyright (C) 2019-2020 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// 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/>.
use crate::{Expression, FormattedString}; use crate::{Expression, FormattedString};
use leo_ast::console::{ use leo_ast::console::{
ConsoleAssert as AstConsoleAssert, ConsoleAssert as AstConsoleAssert,

View File

@ -1,3 +1,19 @@
// Copyright (C) 2019-2020 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// 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/>.
use crate::{ConsoleFunction, Span}; use crate::{ConsoleFunction, Span};
use leo_ast::console::ConsoleFunctionCall as AstConsoleFunctionCall; use leo_ast::console::ConsoleFunctionCall as AstConsoleFunctionCall;

View File

@ -1,3 +1,19 @@
// Copyright (C) 2019-2020 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// 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/>.
pub mod console_function; pub mod console_function;
pub use console_function::*; pub use console_function::*;

View File

@ -275,7 +275,7 @@ impl<'ast> fmt::Display for Expression {
impl<'ast> From<CircuitInlineExpression<'ast>> for Expression { impl<'ast> From<CircuitInlineExpression<'ast>> for Expression {
fn from(expression: CircuitInlineExpression<'ast>) -> Self { fn from(expression: CircuitInlineExpression<'ast>) -> Self {
let circuit_name = Identifier::from(expression.identifier); let circuit_name = Identifier::from(expression.name);
let members = expression let members = expression
.members .members
.into_iter() .into_iter()
@ -288,7 +288,7 @@ impl<'ast> From<CircuitInlineExpression<'ast>> for Expression {
impl<'ast> From<PostfixExpression<'ast>> for Expression { impl<'ast> From<PostfixExpression<'ast>> for Expression {
fn from(expression: PostfixExpression<'ast>) -> Self { fn from(expression: PostfixExpression<'ast>) -> Self {
let variable = Expression::Identifier(Identifier::from(expression.identifier)); let variable = Expression::Identifier(Identifier::from(expression.name));
// ast::PostFixExpression contains an array of "accesses": `a(34)[42]` is represented as `[a, [Call(34), Select(42)]]`, but Access call expressions // ast::PostFixExpression contains an array of "accesses": `a(34)[42]` is represented as `[a, [Call(34), Select(42)]]`, but Access call expressions
// are recursive, so it is `Select(Call(a, 34), 42)`. We apply this transformation here // are recursive, so it is `Select(Call(a, 34), 42)`. We apply this transformation here

View File

@ -33,7 +33,7 @@ impl<'ast> From<AstFunctionInput<'ast>> for FunctionInput {
FunctionInput { FunctionInput {
identifier: Identifier::from(parameter.identifier), identifier: Identifier::from(parameter.identifier),
mutable: parameter.mutable.is_some(), mutable: parameter.mutable.is_some(),
type_: Type::from(parameter._type), type_: Type::from(parameter.type_),
span: Span::from(parameter.span), span: Span::from(parameter.span),
} }
} }