mirror of
https://github.com/AleoHQ/leo.git
synced 2024-12-01 18:56:38 +03:00
pass mutable reference to circuit variable when 'mut self' keyword is present
This commit is contained in:
parent
74f7749462
commit
82e13edbbe
@ -68,6 +68,14 @@ impl Function {
|
||||
self.input.iter().find(|param| param.is_self()).is_some()
|
||||
}
|
||||
|
||||
///
|
||||
/// Returns `true` if the function has input `mut self`.
|
||||
/// Returns `false` otherwise.
|
||||
///
|
||||
pub fn contains_mut_self(&self) -> bool {
|
||||
self.input.iter().find(|param| param.is_mut_self()).is_some()
|
||||
}
|
||||
|
||||
fn format(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "function {}", self.identifier)?;
|
||||
|
||||
|
@ -56,6 +56,19 @@ impl FunctionInput {
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Returns `true` if the function input is the `mut self` keyword.
|
||||
/// Returns `false` otherwise.
|
||||
///
|
||||
pub fn is_mut_self(&self) -> bool {
|
||||
match self {
|
||||
FunctionInput::InputKeyword(_) => false,
|
||||
FunctionInput::SelfKeyword(_) => false,
|
||||
FunctionInput::MutSelfKeyword(_) => true,
|
||||
FunctionInput::Variable(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn format(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
FunctionInput::InputKeyword(keyword) => write!(f, "{}", keyword),
|
||||
|
@ -46,22 +46,22 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
for (input_model, input_expression) in function.input.iter().zip(input.into_iter()) {
|
||||
let (name, value) = match input_model {
|
||||
FunctionInput::InputKeyword(keyword) => {
|
||||
let input_value =
|
||||
let value =
|
||||
self.enforce_function_input(cs, scope, caller_scope, &function_name, None, input_expression)?;
|
||||
|
||||
(keyword.to_string(), input_value)
|
||||
(keyword.to_string(), value)
|
||||
}
|
||||
FunctionInput::SelfKeyword(keyword) => {
|
||||
let input_value =
|
||||
let value =
|
||||
self.enforce_function_input(cs, scope, caller_scope, &function_name, None, input_expression)?;
|
||||
|
||||
(keyword.to_string(), input_value)
|
||||
(keyword.to_string(), value)
|
||||
}
|
||||
FunctionInput::MutSelfKeyword(keyword) => {
|
||||
let input_value =
|
||||
let value =
|
||||
self.enforce_function_input(cs, scope, caller_scope, &function_name, None, input_expression)?;
|
||||
|
||||
(keyword.to_string(), input_value)
|
||||
(keyword.to_string(), value)
|
||||
}
|
||||
FunctionInput::Variable(input_model) => {
|
||||
// First evaluate input expression
|
||||
@ -87,6 +87,8 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
self.store(input_program_identifier, value);
|
||||
}
|
||||
|
||||
let mut_self = function.contains_mut_self();
|
||||
|
||||
// Evaluate every statement in the function and save all potential results
|
||||
let mut results = vec![];
|
||||
|
||||
@ -99,6 +101,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
statement.clone(),
|
||||
function.output.clone(),
|
||||
declared_circuit_reference,
|
||||
mut_self,
|
||||
)?;
|
||||
|
||||
results.append(&mut result);
|
||||
|
@ -42,6 +42,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
file_scope: &str,
|
||||
function_scope: &str,
|
||||
declared_circuit_reference: &str,
|
||||
mut_self: bool,
|
||||
indicator: Option<Boolean>,
|
||||
assignee: Assignee,
|
||||
expression: Expression,
|
||||
@ -88,7 +89,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
}
|
||||
AssigneeAccess::Member(identifier) => {
|
||||
// Mutate a circuit variable using the self keyword.
|
||||
if assignee.identifier.is_self() {
|
||||
if assignee.identifier.is_self() && mut_self {
|
||||
let self_circuit_variable_name = new_scope(&assignee.identifier.name, &identifier.name);
|
||||
let self_variable_name = new_scope(file_scope, &self_circuit_variable_name);
|
||||
let value = self.mutate_circuit_variable(
|
||||
|
@ -89,12 +89,31 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
|
||||
Ok(selected_value)
|
||||
}
|
||||
_ => {
|
||||
// Throw an error if we try to mutate an immutable circuit variable
|
||||
Err(StatementError::immutable_circuit_variable(
|
||||
variable_name.name,
|
||||
value => {
|
||||
// Check that the new value type == old value type
|
||||
new_value.resolve_type(Some(value.to_type(span)?), span)?;
|
||||
|
||||
// Conditionally select the value if this branch is executed.
|
||||
let mut selected_value = ConstrainedValue::conditionally_select(
|
||||
cs.ns(|| format!("select {} {}:{}", new_value, span.line, span.start)),
|
||||
&condition,
|
||||
&new_value,
|
||||
&member.1,
|
||||
)
|
||||
.map_err(|_| {
|
||||
StatementError::select_fail(
|
||||
new_value.to_string(),
|
||||
member.1.to_string(),
|
||||
span.to_owned(),
|
||||
))
|
||||
)
|
||||
})?;
|
||||
|
||||
// Make sure the new value is still mutable
|
||||
selected_value = ConstrainedValue::Mutable(Box::new(selected_value));
|
||||
|
||||
member.1 = selected_value.to_owned();
|
||||
|
||||
Ok(selected_value)
|
||||
}
|
||||
},
|
||||
None => {
|
||||
|
@ -33,6 +33,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
indicator: Option<Boolean>,
|
||||
statements: Vec<Statement>,
|
||||
return_type: Option<Type>,
|
||||
mut_self: bool,
|
||||
) -> StatementResult<Vec<IndicatorAndConstrainedValue<F, G>>> {
|
||||
let mut results = Vec::with_capacity(statements.len());
|
||||
// Evaluate statements. Only allow a single return argument to be returned.
|
||||
@ -45,6 +46,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
statement,
|
||||
return_type.clone(),
|
||||
"",
|
||||
mut_self,
|
||||
)?;
|
||||
|
||||
results.append(&mut value);
|
||||
|
@ -52,6 +52,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
indicator: Option<Boolean>,
|
||||
statement: ConditionalStatement,
|
||||
return_type: Option<Type>,
|
||||
mut_self: bool,
|
||||
span: &Span,
|
||||
) -> StatementResult<Vec<IndicatorAndConstrainedValue<F, G>>> {
|
||||
let statement_string = statement.to_string();
|
||||
@ -95,6 +96,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
Some(branch_1_indicator),
|
||||
statement.statements,
|
||||
return_type.clone(),
|
||||
mut_self,
|
||||
)?;
|
||||
|
||||
results.append(&mut branch_1_result);
|
||||
@ -123,6 +125,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
Some(branch_2_indicator),
|
||||
*nested,
|
||||
return_type,
|
||||
mut_self,
|
||||
span,
|
||||
)?,
|
||||
ConditionalNestedOrEndStatement::End(statements) => self.evaluate_branch(
|
||||
@ -132,6 +135,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
Some(branch_2_indicator),
|
||||
statements,
|
||||
return_type,
|
||||
mut_self,
|
||||
)?,
|
||||
},
|
||||
None => vec![],
|
||||
|
@ -48,6 +48,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
stop: Expression,
|
||||
statements: Vec<Statement>,
|
||||
return_type: Option<Type>,
|
||||
mut_self: bool,
|
||||
span: &Span,
|
||||
) -> StatementResult<Vec<IndicatorAndConstrainedValue<F, G>>> {
|
||||
let mut results = vec![];
|
||||
@ -74,6 +75,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
indicator,
|
||||
statements.clone(),
|
||||
return_type.clone(),
|
||||
mut_self,
|
||||
)?;
|
||||
|
||||
results.append(&mut result);
|
||||
|
@ -45,6 +45,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
statement: Statement,
|
||||
return_type: Option<Type>,
|
||||
declared_circuit_reference: &str,
|
||||
mut_self: bool,
|
||||
) -> StatementResult<Vec<IndicatorAndConstrainedValue<F, G>>> {
|
||||
let mut results = vec![];
|
||||
|
||||
@ -74,6 +75,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
file_scope,
|
||||
function_scope,
|
||||
declared_circuit_reference,
|
||||
mut_self,
|
||||
indicator,
|
||||
variable,
|
||||
expression,
|
||||
@ -88,6 +90,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
indicator,
|
||||
statement,
|
||||
return_type,
|
||||
mut_self,
|
||||
&span,
|
||||
)?;
|
||||
|
||||
@ -104,6 +107,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
start_stop.1,
|
||||
statements,
|
||||
return_type,
|
||||
mut_self,
|
||||
&span,
|
||||
)?;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user