mirror of
https://github.com/AleoHQ/leo.git
synced 2024-11-29 03:35:10 +03:00
const func arguments
This commit is contained in:
parent
90fc6a9c12
commit
9c6eb23a1e
@ -29,7 +29,7 @@ use crate::{
|
||||
Span,
|
||||
Type,
|
||||
};
|
||||
pub use leo_ast::BinaryOperation;
|
||||
pub use leo_ast::{BinaryOperation, Node as AstNode};
|
||||
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
@ -194,25 +194,33 @@ impl FromAst<leo_ast::CallExpression> for CallExpression {
|
||||
));
|
||||
}
|
||||
}
|
||||
if value.arguments.len() != function.argument_types.len() {
|
||||
if value.arguments.len() != function.arguments.len() {
|
||||
return Err(AsgConvertError::unexpected_call_argument_count(
|
||||
function.argument_types.len(),
|
||||
function.arguments.len(),
|
||||
value.arguments.len(),
|
||||
&value.span,
|
||||
));
|
||||
}
|
||||
|
||||
let arguments = value
|
||||
.arguments
|
||||
.iter()
|
||||
.zip(function.arguments.iter())
|
||||
.map(|(expr, argument)| {
|
||||
let argument = argument.borrow();
|
||||
let converted =
|
||||
Arc::<Expression>::from_ast(scope, expr, Some(argument.type_.clone().strong().partial()))?;
|
||||
if argument.const_ && !converted.is_consty() {
|
||||
return Err(AsgConvertError::unexpected_nonconst(&expr.span()));
|
||||
}
|
||||
Ok(converted)
|
||||
})
|
||||
.collect::<Result<Vec<_>, AsgConvertError>>()?;
|
||||
|
||||
Ok(CallExpression {
|
||||
parent: RefCell::new(None),
|
||||
span: Some(value.span.clone()),
|
||||
arguments: value
|
||||
.arguments
|
||||
.iter()
|
||||
.zip(function.argument_types.iter())
|
||||
.map(|(expr, argument)| {
|
||||
Arc::<Expression>::from_ast(scope, expr, Some(argument.clone().strong().partial()))
|
||||
})
|
||||
.collect::<Result<Vec<_>, AsgConvertError>>()?,
|
||||
arguments,
|
||||
function,
|
||||
target,
|
||||
})
|
||||
|
@ -29,7 +29,6 @@ use crate::{
|
||||
Statement,
|
||||
Type,
|
||||
Variable,
|
||||
VariableDeclaration,
|
||||
};
|
||||
|
||||
use std::{
|
||||
@ -61,7 +60,7 @@ impl ExpressionNode for VariableRef {
|
||||
fn enforce_parents(&self, _expr: &Arc<Expression>) {}
|
||||
|
||||
fn get_type(&self) -> Option<Type> {
|
||||
Some(self.variable.borrow().type_.clone())
|
||||
Some(self.variable.borrow().type_.clone().strong().clone())
|
||||
}
|
||||
|
||||
fn is_mut_ref(&self) -> bool {
|
||||
@ -103,7 +102,7 @@ impl ExpressionNode for VariableRef {
|
||||
|
||||
fn is_consty(&self) -> bool {
|
||||
let variable = self.variable.borrow();
|
||||
if variable.declaration == VariableDeclaration::IterationDefinition {
|
||||
if variable.const_ {
|
||||
return true;
|
||||
}
|
||||
if variable.mutable || variable.assignments.len() != 1 {
|
||||
|
@ -127,8 +127,9 @@ impl Input {
|
||||
container: Arc::new(RefCell::new(crate::InnerVariable {
|
||||
id: uuid::Uuid::new_v4(),
|
||||
name: Identifier::new("input".to_string()),
|
||||
type_: Type::Circuit(container_circuit),
|
||||
type_: Type::Circuit(container_circuit).weak(),
|
||||
mutable: false,
|
||||
const_: false,
|
||||
declaration: crate::VariableDeclaration::Input,
|
||||
references: vec![],
|
||||
assignments: vec![],
|
||||
|
@ -50,7 +50,7 @@ pub struct Function {
|
||||
pub name: RefCell<Identifier>,
|
||||
pub output: WeakType,
|
||||
pub has_input: bool,
|
||||
pub argument_types: Vec<WeakType>,
|
||||
pub arguments: Vec<Variable>,
|
||||
pub circuit: RefCell<Option<Weak<Circuit>>>,
|
||||
pub body: RefCell<Weak<FunctionBody>>,
|
||||
pub qualifier: FunctionQualifier,
|
||||
@ -69,7 +69,6 @@ impl Eq for Function {}
|
||||
pub struct FunctionBody {
|
||||
pub span: Option<Span>,
|
||||
pub function: Arc<Function>,
|
||||
pub arguments: Vec<Variable>,
|
||||
pub body: Arc<Statement>,
|
||||
pub scope: Scope,
|
||||
}
|
||||
@ -92,7 +91,7 @@ impl Function {
|
||||
let mut qualifier = FunctionQualifier::Static;
|
||||
let mut has_input = false;
|
||||
|
||||
let mut argument_types = vec![];
|
||||
let mut arguments = vec![];
|
||||
{
|
||||
for input in value.input.iter() {
|
||||
match input {
|
||||
@ -105,8 +104,24 @@ impl Function {
|
||||
FunctionInput::MutSelfKeyword(_) => {
|
||||
qualifier = FunctionQualifier::MutSelfRef;
|
||||
}
|
||||
FunctionInput::Variable(leo_ast::FunctionInputVariable { type_, .. }) => {
|
||||
argument_types.push(scope.borrow().resolve_ast_type(&type_)?.into());
|
||||
FunctionInput::Variable(leo_ast::FunctionInputVariable {
|
||||
identifier,
|
||||
mutable,
|
||||
const_,
|
||||
type_,
|
||||
span: _span,
|
||||
}) => {
|
||||
let variable = Arc::new(RefCell::new(crate::InnerVariable {
|
||||
id: Uuid::new_v4(),
|
||||
name: identifier.clone(),
|
||||
type_: scope.borrow().resolve_ast_type(&type_)?.weak(),
|
||||
mutable: *mutable,
|
||||
const_: *const_,
|
||||
declaration: crate::VariableDeclaration::Parameter,
|
||||
references: vec![],
|
||||
assignments: vec![],
|
||||
}));
|
||||
arguments.push(variable.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -119,7 +134,7 @@ impl Function {
|
||||
name: RefCell::new(value.identifier.clone()),
|
||||
output: output.into(),
|
||||
has_input,
|
||||
argument_types,
|
||||
arguments,
|
||||
circuit: RefCell::new(None),
|
||||
body: RefCell::new(Weak::new()),
|
||||
qualifier,
|
||||
@ -134,7 +149,6 @@ impl FunctionBody {
|
||||
function: Arc<Function>,
|
||||
) -> Result<FunctionBody, AsgConvertError> {
|
||||
let new_scope = InnerScope::make_subscope(scope);
|
||||
let mut arguments = vec![];
|
||||
{
|
||||
let mut scope_borrow = new_scope.borrow_mut();
|
||||
if function.qualifier != FunctionQualifier::Static {
|
||||
@ -142,8 +156,9 @@ impl FunctionBody {
|
||||
let self_variable = Arc::new(RefCell::new(crate::InnerVariable {
|
||||
id: Uuid::new_v4(),
|
||||
name: Identifier::new("self".to_string()),
|
||||
type_: Type::Circuit(circuit.as_ref().unwrap().upgrade().unwrap()),
|
||||
type_: WeakType::Circuit(circuit.as_ref().unwrap().clone()),
|
||||
mutable: function.qualifier == FunctionQualifier::MutSelfRef,
|
||||
const_: false,
|
||||
declaration: crate::VariableDeclaration::Parameter,
|
||||
references: vec![],
|
||||
assignments: vec![],
|
||||
@ -151,30 +166,9 @@ impl FunctionBody {
|
||||
scope_borrow.variables.insert("self".to_string(), self_variable);
|
||||
}
|
||||
scope_borrow.function = Some(function.clone());
|
||||
for input in value.input.iter() {
|
||||
match input {
|
||||
FunctionInput::InputKeyword(_) => {}
|
||||
FunctionInput::SelfKeyword(_) => {}
|
||||
FunctionInput::MutSelfKeyword(_) => {}
|
||||
FunctionInput::Variable(leo_ast::FunctionInputVariable {
|
||||
identifier,
|
||||
mutable,
|
||||
type_,
|
||||
span: _span,
|
||||
}) => {
|
||||
let variable = Arc::new(RefCell::new(crate::InnerVariable {
|
||||
id: Uuid::new_v4(),
|
||||
name: identifier.clone(),
|
||||
type_: scope_borrow.resolve_ast_type(&type_)?,
|
||||
mutable: *mutable,
|
||||
declaration: crate::VariableDeclaration::Parameter,
|
||||
references: vec![],
|
||||
assignments: vec![],
|
||||
}));
|
||||
arguments.push(variable.clone());
|
||||
scope_borrow.variables.insert(identifier.name.clone(), variable);
|
||||
}
|
||||
}
|
||||
for argument in function.arguments.iter() {
|
||||
let name = argument.borrow().name.name.clone();
|
||||
scope_borrow.variables.insert(name, argument.clone());
|
||||
}
|
||||
}
|
||||
let main_block = BlockStatement::from_ast(&new_scope, &value.block, None)?;
|
||||
@ -198,7 +192,6 @@ impl FunctionBody {
|
||||
Ok(FunctionBody {
|
||||
span: Some(value.span.clone()),
|
||||
function,
|
||||
arguments,
|
||||
body: Arc::new(Statement::Block(main_block)),
|
||||
scope: new_scope,
|
||||
})
|
||||
@ -209,14 +202,16 @@ impl Into<leo_ast::Function> for &Function {
|
||||
fn into(self) -> leo_ast::Function {
|
||||
let (input, body, span) = match self.body.borrow().upgrade() {
|
||||
Some(body) => (
|
||||
body.arguments
|
||||
body.function
|
||||
.arguments
|
||||
.iter()
|
||||
.map(|variable| {
|
||||
let variable = variable.borrow();
|
||||
leo_ast::FunctionInput::Variable(leo_ast::FunctionInputVariable {
|
||||
identifier: variable.name.clone(),
|
||||
mutable: variable.mutable,
|
||||
type_: (&variable.type_).into(),
|
||||
const_: variable.const_,
|
||||
type_: (&variable.type_.clone().strong()).into(),
|
||||
span: Span::default(),
|
||||
})
|
||||
})
|
||||
|
@ -92,7 +92,7 @@ impl FromAst<leo_ast::AssignStatement> for Arc<Statement> {
|
||||
if !variable.borrow().mutable {
|
||||
return Err(AsgConvertError::immutable_assignment(&name, &statement.span));
|
||||
}
|
||||
let mut target_type: Option<PartialType> = Some(variable.borrow().type_.clone().into());
|
||||
let mut target_type: Option<PartialType> = Some(variable.borrow().type_.clone().strong().into());
|
||||
|
||||
let mut target_accesses = vec![];
|
||||
for access in statement.assignee.accesses.iter() {
|
||||
|
@ -98,8 +98,10 @@ impl FromAst<leo_ast::DefinitionStatement> for Arc<Statement> {
|
||||
id: uuid::Uuid::new_v4(),
|
||||
name: variable.identifier.clone(),
|
||||
type_: type_
|
||||
.ok_or_else(|| AsgConvertError::unresolved_type(&variable.identifier.name, &statement.span))?,
|
||||
.ok_or_else(|| AsgConvertError::unresolved_type(&variable.identifier.name, &statement.span))?
|
||||
.weak(),
|
||||
mutable: variable.mutable,
|
||||
const_: false,
|
||||
declaration: crate::VariableDeclaration::Definition,
|
||||
references: vec![],
|
||||
assignments: vec![],
|
||||
@ -144,7 +146,7 @@ impl Into<leo_ast::DefinitionStatement> for &DefinitionStatement {
|
||||
span: variable.name.span.clone(),
|
||||
});
|
||||
if type_.is_none() {
|
||||
type_ = Some((&variable.type_).into());
|
||||
type_ = Some((&variable.type_.clone().strong()).into());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -64,8 +64,10 @@ impl FromAst<leo_ast::IterationStatement> for Arc<Statement> {
|
||||
name: statement.variable.clone(),
|
||||
type_: start
|
||||
.get_type()
|
||||
.ok_or_else(|| AsgConvertError::unresolved_type(&statement.variable.name, &statement.span))?,
|
||||
.ok_or_else(|| AsgConvertError::unresolved_type(&statement.variable.name, &statement.span))?
|
||||
.weak(),
|
||||
mutable: false,
|
||||
const_: true,
|
||||
declaration: crate::VariableDeclaration::IterationDefinition,
|
||||
references: vec![],
|
||||
assignments: vec![],
|
||||
|
@ -157,6 +157,10 @@ impl Type {
|
||||
self.into()
|
||||
}
|
||||
|
||||
pub fn weak(self) -> WeakType {
|
||||
self.into()
|
||||
}
|
||||
|
||||
pub fn is_unit(&self) -> bool {
|
||||
matches!(self, Type::Tuple(t) if t.is_empty())
|
||||
}
|
||||
|
@ -14,7 +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::{Expression, Statement, Type};
|
||||
use crate::{Expression, Statement, WeakType};
|
||||
use leo_ast::Identifier;
|
||||
|
||||
use std::{
|
||||
@ -36,8 +36,9 @@ pub enum VariableDeclaration {
|
||||
pub struct InnerVariable {
|
||||
pub id: Uuid,
|
||||
pub name: Identifier,
|
||||
pub type_: Type,
|
||||
pub type_: WeakType,
|
||||
pub mutable: bool,
|
||||
pub const_: bool, // only function arguments, const var definitions NOT included
|
||||
pub declaration: VariableDeclaration,
|
||||
pub references: Vec<Weak<Expression>>, // all Expression::VariableRef or panic
|
||||
pub assignments: Vec<Weak<Statement>>, // all Statement::Assign or panic -- must be 1 if not mutable, or 0 if declaration == input | parameter
|
||||
|
@ -44,6 +44,66 @@ fn test_iteration() {
|
||||
load_asg(program_string).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_const_args() {
|
||||
let program_string = r#"
|
||||
function one(const value: u32) -> u32 {
|
||||
return value + 1
|
||||
}
|
||||
|
||||
function main() {
|
||||
let mut a = 0u32;
|
||||
|
||||
for i in 0..10 {
|
||||
a += one(i);
|
||||
}
|
||||
|
||||
console.assert(a == 20u32);
|
||||
}
|
||||
"#;
|
||||
load_asg(program_string).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_const_args_used() {
|
||||
let program_string = r#"
|
||||
function index(arr: [u8; 3], const value: u32) -> u8 {
|
||||
return arr[value]
|
||||
}
|
||||
|
||||
function main() {
|
||||
let mut a = 0u8;
|
||||
let arr = [1u8, 2, 3];
|
||||
|
||||
for i in 0..3 {
|
||||
a += index(arr, i);
|
||||
}
|
||||
|
||||
console.assert(a == 6u8);
|
||||
}
|
||||
"#;
|
||||
load_asg(program_string).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_const_args_fail() {
|
||||
let program_string = r#"
|
||||
function index(arr: [u8; 3], const value: u32) -> u8 {
|
||||
return arr[value]
|
||||
}
|
||||
|
||||
function main(x_value: u32) {
|
||||
let mut a = 0u8;
|
||||
let arr = [1u8, 2, 3];
|
||||
|
||||
a += index(arr, x_value);
|
||||
|
||||
console.assert(a == 1u8);
|
||||
}
|
||||
"#;
|
||||
load_asg(program_string).err().unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_iteration_repeated() {
|
||||
let program_string = include_str!("iteration_repeated.leo");
|
||||
|
@ -81,7 +81,6 @@ fn test_function_input_mut() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn test_swap() {
|
||||
let program_string = include_str!("swap.leo");
|
||||
load_asg(program_string).unwrap();
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Swap two elements of an array.
|
||||
function swap(mut a: [u32; 2], i: u32, j: u32) -> [u32; 2] {
|
||||
function swap(mut a: [u32; 2], const i: u32, const j: u32) -> [u32; 2] {
|
||||
let t = a[i];
|
||||
a[i] = a[j];
|
||||
a[j] = t;
|
||||
|
@ -23,6 +23,7 @@ use std::fmt;
|
||||
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct FunctionInputVariable {
|
||||
pub identifier: Identifier,
|
||||
pub const_: bool,
|
||||
pub mutable: bool,
|
||||
pub type_: Type,
|
||||
pub span: Span,
|
||||
@ -32,6 +33,7 @@ impl<'ast> From<GrammarFunctionInput<'ast>> for FunctionInputVariable {
|
||||
fn from(parameter: GrammarFunctionInput<'ast>) -> Self {
|
||||
FunctionInputVariable {
|
||||
identifier: Identifier::from(parameter.identifier),
|
||||
const_: parameter.const_.is_some(),
|
||||
mutable: parameter.mutable.is_some(),
|
||||
type_: Type::from(parameter.type_),
|
||||
span: Span::from(parameter.span),
|
||||
@ -42,6 +44,9 @@ impl<'ast> From<GrammarFunctionInput<'ast>> for FunctionInputVariable {
|
||||
impl FunctionInputVariable {
|
||||
fn format(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
// mut var: bool
|
||||
if self.mutable {
|
||||
write!(f, "const ")?;
|
||||
}
|
||||
if self.mutable {
|
||||
write!(f, "mut ")?;
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
None
|
||||
};
|
||||
|
||||
if function.arguments.len() != arguments.len() {
|
||||
if function.function.arguments.len() != arguments.len() {
|
||||
return Err(FunctionError::input_not_found(
|
||||
"arguments length invalid".to_string(),
|
||||
function.span.clone().unwrap_or_default(),
|
||||
@ -60,7 +60,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
}
|
||||
|
||||
// Store input values as new variables in resolved program
|
||||
for (variable, input_expression) in function.arguments.iter().zip(arguments.iter()) {
|
||||
for (variable, input_expression) in function.function.arguments.iter().zip(arguments.iter()) {
|
||||
let input_value = self.enforce_expression(cs, input_expression)?;
|
||||
let variable = variable.borrow();
|
||||
|
||||
|
@ -64,7 +64,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
|
||||
let mut arguments = vec![];
|
||||
|
||||
for input_variable in function.arguments.iter() {
|
||||
for input_variable in function.function.arguments.iter() {
|
||||
{
|
||||
let input_variable = input_variable.borrow();
|
||||
let name = input_variable.name.name.clone();
|
||||
@ -73,7 +73,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
})?;
|
||||
let input_value = self.allocate_main_function_input(
|
||||
cs,
|
||||
&input_variable.type_,
|
||||
&input_variable.type_.clone().strong(),
|
||||
&name,
|
||||
input_option,
|
||||
&function.span.clone().unwrap_or_default(),
|
||||
|
@ -7,7 +7,7 @@ circuit PedersenHash {
|
||||
}
|
||||
|
||||
function hash(self, bits: [bool; 256]) -> group {
|
||||
let mut digest: group = 0;
|
||||
let mut digest: group = 0group;
|
||||
for i in 0..256 {
|
||||
if bits[i] {
|
||||
digest += self.parameters[i];
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
use crate::{
|
||||
ast::Rule,
|
||||
common::{Identifier, Mutable},
|
||||
common::{Const, Identifier, Mutable},
|
||||
types::Type,
|
||||
SpanDef,
|
||||
};
|
||||
@ -28,6 +28,7 @@ use serde::Serialize;
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
||||
#[pest_ast(rule(Rule::function_input))]
|
||||
pub struct FunctionInput<'ast> {
|
||||
pub const_: Option<Const>,
|
||||
pub mutable: Option<Mutable>,
|
||||
pub identifier: Identifier<'ast>,
|
||||
pub type_: Type<'ast>,
|
||||
|
@ -430,7 +430,7 @@ statement_return = { "return " ~ expression}
|
||||
function = { "function " ~ identifier ~ input_tuple ~ ("->" ~ type_)? ~ block }
|
||||
|
||||
// Declared in functions/input/function_input.rs
|
||||
function_input = { mutable? ~ identifier ~ ":" ~ type_ }
|
||||
function_input = { const_? ~ mutable? ~ identifier ~ ":" ~ type_ }
|
||||
|
||||
// Declared in functions/input/input_keyword.rs
|
||||
input_keyword = { "input" }
|
||||
|
Loading…
Reference in New Issue
Block a user