remove mut circuit variable definition

This commit is contained in:
collin 2020-12-01 11:54:51 -05:00
parent 7977b20ad2
commit 8457b05354
13 changed files with 93 additions and 40 deletions

View File

@ -66,7 +66,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
match matched_variable {
Some(variable) => {
// Resolve and enforce circuit variable
let mut variable_value = self.enforce_expression(
let variable_value = self.enforce_expression(
cs,
file_scope,
function_scope,

View File

@ -3,7 +3,7 @@ circuit Foo {
}
circuit Bar {
static function bar() {
function bar() {
let f = Foo { a: 0u32 };
}
}

View File

@ -1,5 +1,5 @@
circuit Foo {
static function echo(x: u32) -> u32 {
function echo(x: u32) -> u32 {
return x
}
}

View File

@ -1,11 +1,11 @@
circuit Foo {
x: u32,
function add_x(y: u32) -> u32 {
function add_x(self, y: u32) -> u32 {
return self.x + y
}
function call_add_x(y: u32) -> u32 {
function call_add_x(self, y: u32) -> u32 {
return self.add_x(y)
}
}

View File

@ -14,7 +14,13 @@
// 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, expect_type_inference_error, parse_program};
use crate::{
assert_satisfied,
expect_compiler_error,
expect_symbol_table_error,
expect_type_inference_error,
parse_program,
};
// Expressions

View File

@ -1,6 +1,6 @@
// Adding the `mut` keyword makes a circuit variable mutable.
circuit Foo {
static function bar() {}
function bar() {}
}
function main() {

View File

@ -1,6 +1,6 @@
// Adding the `mut` keyword makes a circuit variable mutable.
circuit Foo {
mut x: u32
x: u32
}
function main() {

View File

@ -78,7 +78,7 @@ fn test_circuit_mut() {
let bytes = include_bytes!("circuit_mut.leo");
let program = parse_program(bytes).unwrap();
expect_compiler_error(program);
assert_satisfied(program);
}
#[test]

View File

@ -14,12 +14,7 @@
// 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,
common::{Identifier, Mutable},
types::Type,
SpanDef,
};
use crate::{ast::Rule, common::Identifier, types::Type, SpanDef};
use pest::Span;
use pest_ast::FromPest;

View File

@ -129,6 +129,14 @@ impl FunctionType {
.iter()
.fold(0, |acc, function_input| acc + function_input.count())
}
///
/// Returns `true` if the input `self` or `mut self` is present.
/// Returns `false` otherwise.
///
pub fn contains_self(&self) -> bool {
self.inputs.iter().find(|param| param.is_self()).is_some()
}
}
impl PartialEq for FunctionType {

View File

@ -65,17 +65,25 @@ impl FunctionInputType {
}
///
/// Returns `1` if a variable must be provided in a call to the function.
/// Returns `true` if input `self` or `mut self` is present.
/// Returns `false` otherwise.
///
pub fn is_self(&self) -> bool {
match self {
FunctionInputType::InputKeyword(_) => false,
FunctionInputType::SelfKeyword(_) => true,
FunctionInputType::MutSelfKeyword(_) => true,
FunctionInputType::Variable(_) => false,
}
}
///
/// Returns `0` if the function input is a `self` or `mut self` keyword which does not have to
/// provided in a call to the function.
/// Returns `1` if a variable must be provided in a call to the function.
///
pub fn count(&self) -> usize {
match self {
FunctionInputType::InputKeyword(_) => 1,
FunctionInputType::SelfKeyword(_) => 0,
FunctionInputType::MutSelfKeyword(_) => 0,
FunctionInputType::Variable(_) => 1,
}
if self.is_self() { 0 } else { 1 }
}
///

View File

@ -172,6 +172,27 @@ impl FrameError {
Self::new_from_span(message, span)
}
///
/// The `self` keyword was used in a static circuit function signature.
///
pub fn self_not_available(span: &Span) -> Self {
let message = "keyword `self` is only available in static circuit functions.".to_string();
Self::new_from_span(message, span)
}
///
/// A static function was accessed using dot `.` syntax instead of double colon `::` syntax.
///
pub fn static_call_invalid(identifier: &Identifier) -> Self {
let message = format!(
"Static function `{}` must be called using double colon `::` syntax.",
identifier.name
);
Self::new_from_span(message, &identifier.span)
}
///
/// Attempted to access the index of a non-tuple type.
///

View File

@ -952,22 +952,6 @@ impl Frame {
Ok(Type::Circuit(circuit_type.identifier))
}
///
/// Returns the type of the accessed circuit member when called as an expression.
///
fn parse_expression_circuit_member_access(
&mut self,
expression: &Expression,
identifier: &Identifier,
span: &Span,
) -> Result<Type, FrameError> {
// Parse circuit name.
let type_ = self.parse_expression(expression)?;
// Parse the circuit member access.
self.parse_circuit_member_access(type_, identifier, span)
}
///
/// Returns the type of the accessed circuit member.
///
@ -984,6 +968,22 @@ impl Frame {
Ok(circuit_type.member_type(&identifier)?)
}
///
/// Returns the type of the accessed circuit member when called as an expression.
///
fn parse_expression_circuit_member_access(
&mut self,
expression: &Expression,
identifier: &Identifier,
span: &Span,
) -> Result<Type, FrameError> {
// Parse circuit name.
let type_ = self.parse_expression(expression)?;
// Parse the circuit member access.
self.parse_circuit_member_access(type_, identifier, span)
}
///
/// Returns the type returned by calling the static circuit function.
///
@ -1026,10 +1026,10 @@ impl Frame {
match expression {
Expression::Identifier(identifier) => self.parse_program_function(identifier, span),
Expression::CircuitMemberAccess(expression, identifier, span) => {
self.parse_circuit_function(expression, identifier, span)
self.parse_circuit_function(expression, identifier, span, false)
}
Expression::CircuitStaticFunctionAccess(expression, identifier, span) => {
self.parse_circuit_function(expression, identifier, span)
self.parse_circuit_function(expression, identifier, span, true)
}
expression => Err(FrameError::invalid_function(expression, span)),
}
@ -1074,10 +1074,25 @@ impl Frame {
expression: &Expression,
identifier: &Identifier,
span: &Span,
is_static: bool,
) -> Result<FunctionType, FrameError> {
// Find circuit function type.
let function_type = self.parse_circuit_function_type(expression, identifier, span)?;
// Case 1: static call + self keyword => Error
// Case 2: no static call + no self keywords => Error
// Case 3: static call + no self keywords => Ok
// Case 4: no static call + self keyword => Ok
println!("static {}", is_static);
println!("function contains self {}", function_type.contains_self());
if is_static && function_type.contains_self() {
return Err(FrameError::self_not_available(&identifier.span));
} else if !is_static && !function_type.contains_self() {
return Err(FrameError::static_call_invalid(&identifier));
}
if is_static && function_type.contains_self() {}
// Return the function type.
Ok(function_type.to_owned())
}