merge master, clean up reducer and directors

This commit is contained in:
gluax 2021-04-09 12:48:59 -04:00
commit bddcef732f
45 changed files with 692 additions and 837 deletions

View File

@ -1,6 +1,6 @@
# leo add (w/o login) & remove
$LEO new my-app && cd my-app
$LEO new my-app && cd my-app || exit 1
$LEO add howard/silly-sudoku
$LEO remove silly-sudoku
$LEO clean

View File

@ -1,4 +1,5 @@
mkdir hello-world && cd hello-world || exit 1
$LEO init
ls -la
mkdir hello-world
cd hello-world
$LEO init || exit 1
ls -la hello-world
$LEO run

52
Cargo.lock generated
View File

@ -4,9 +4,9 @@ version = 3
[[package]]
name = "abnf"
version = "0.10.1"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb23c378acfcb46052bd7d1a6119d8d608d4c12ac6c72cb1d9c4e85bc2cb2bb7"
checksum = "fd8863e7db43447ad50376e19b0549343b72ad45cbd394b3fc8fe3ede961facc"
dependencies = [
"abnf-core",
"nom 6.1.2",
@ -2572,9 +2572,9 @@ checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e"
[[package]]
name = "snarkvm-algorithms"
version = "0.2.1"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "472ed062cdd1f54076312dd34e5fb56bd585c80c12209045f4b5bbbd368e9000"
checksum = "bdf8ca73d429824090b96f751846e37e539f24c527f1f1ce0254984ade6d17b2"
dependencies = [
"blake2",
"derivative",
@ -2595,9 +2595,9 @@ dependencies = [
[[package]]
name = "snarkvm-curves"
version = "0.2.1"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdfdfa3aa137f64a7f49df03393e5d0269f133ca8c8c79e569cb3bb13181aeb2"
checksum = "64610b135b8b1152439d5dfa4f745515933366082f08651961344aa0bb5abfca"
dependencies = [
"derivative",
"rand",
@ -2611,9 +2611,9 @@ dependencies = [
[[package]]
name = "snarkvm-derives"
version = "0.2.1"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a2ba967601ff2534adbc6a71a691be4285e61c83d23d54a59824f8fa80f6038"
checksum = "46c9829b6e2023b4c7c4d6c55e88fe755dd997171a6c9c063b75c28161d04326"
dependencies = [
"proc-macro-crate",
"proc-macro-error",
@ -2624,9 +2624,9 @@ dependencies = [
[[package]]
name = "snarkvm-dpc"
version = "0.2.1"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff4cb55898089843ba44b9f96448dcb2badcc1ce12daa8d7365d4e41513e37bc"
checksum = "491ae936e24e17c358d112ff8638b260500b5a982ecefc804861e28b5279f552"
dependencies = [
"anyhow",
"base58",
@ -2650,9 +2650,9 @@ dependencies = [
[[package]]
name = "snarkvm-fields"
version = "0.2.1"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca9ea954196e76fe8968fb99eced7ccf08f901ab22747c4c489bda6674a7cb39"
checksum = "8c49c69d02df11be58e07f626c9d6f5804c6dd4ccf42e425f2be8d79fe6e5bb7"
dependencies = [
"bincode",
"derivative",
@ -2665,9 +2665,9 @@ dependencies = [
[[package]]
name = "snarkvm-gadgets"
version = "0.2.1"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fdda42a0a6484d9f008801a8a4d494a69a4db3f7b317057a8cc3c6e4b3ef6884"
checksum = "bd6f9ac2a166d926e1755a06fdae21ce40ce6164c75c89120401b8d78f3b7ba4"
dependencies = [
"derivative",
"digest 0.9.0",
@ -2682,9 +2682,9 @@ dependencies = [
[[package]]
name = "snarkvm-objects"
version = "0.2.1"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e20d13db49cedc147df06c4a6f2dd727ea25640bdf50b876f40005331767a68f"
checksum = "9bd9779ec6ab9211f34a6ba25566feb575a396f4c41cc0e002ec2d48d7560a2a"
dependencies = [
"anyhow",
"bincode",
@ -2703,9 +2703,9 @@ dependencies = [
[[package]]
name = "snarkvm-parameters"
version = "0.2.1"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d35fa1819d803e45b4e99fe822e6981f177716f5384eef27245b5f6ed59a8305"
checksum = "98378f612206fc7dd44a26f4e345bd1f3ba51bd325acad1e5cc3785d14750ec5"
dependencies = [
"curl",
"hex",
@ -2716,15 +2716,15 @@ dependencies = [
[[package]]
name = "snarkvm-profiler"
version = "0.2.1"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7834d57af37a31f2f280f08b61d07a04a9a4b7720819b06ca325da32a5a925f5"
checksum = "b2460ac01c25f79f5ea306e4de82a1d4105e811f868206b4fd31c0c9b62a3d7b"
[[package]]
name = "snarkvm-r1cs"
version = "0.2.1"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0838118f276e7bb673cbf3741f4966c56861aaff399a46d343fc98c12851d9eb"
checksum = "a3a0d54b15802976aff7522765dd29d5733f338612449629cc57c5a4a4d51f05"
dependencies = [
"cfg-if 1.0.0",
"fxhash",
@ -2737,9 +2737,9 @@ dependencies = [
[[package]]
name = "snarkvm-storage"
version = "0.2.1"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a42d92a817502878f315cc264704fa2a3d563755f16186316d8177ea685769af"
checksum = "1d76881939f008d7bba4c8cc4118d29567b5c71908ad66bef9880f8aa7c52881"
dependencies = [
"anyhow",
"bincode",
@ -2758,9 +2758,9 @@ dependencies = [
[[package]]
name = "snarkvm-utilities"
version = "0.2.1"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5598f7f71c8aaf4fc267b5b420b2440a4d86c9243cecd57ff0af5c366217e5cc"
checksum = "c763843fa67a3aa4ce68173c8cd96b4f04aaa135a5792bc051c36eec0fe1cd73"
dependencies = [
"bincode",
"rand",

View File

@ -69,23 +69,23 @@ path = "./synthesizer"
version = "1.2.3"
[dependencies.snarkvm-algorithms]
version = "0.2.1"
version = "0.2.2"
#default-features = false
[dependencies.snarkvm-curves]
version = "0.2.1"
version = "0.2.2"
default-features = false
[dependencies.snarkvm-gadgets]
version = "0.2.1"
version = "0.2.2"
default-features = false
[dependencies.snarkvm-r1cs]
version = "0.2.1"
version = "0.2.2"
default-features = false
[dependencies.snarkvm-utilities]
version = "0.2.1"
version = "0.2.2"
[dependencies.anyhow]
version = "1.0"

View File

@ -172,6 +172,13 @@ impl AsgConvertError {
)
}
pub fn duplicate_function_definition(name: &str, span: &Span) -> Self {
Self::new_from_span(
format!("a function named \"{}\" already exists in this scope", name),
span,
)
}
pub fn index_into_non_tuple(name: &str, span: &Span) -> Self {
Self::new_from_span(format!("failed to index into non-tuple '{}'", name), span)
}

View File

@ -266,7 +266,13 @@ impl<'a> Program<'a> {
asg_function.fill_from_ast(function)?;
functions.insert(name.name.to_string(), asg_function);
let name = name.name.to_string();
if functions.contains_key(&name) {
return Err(AsgConvertError::duplicate_function_definition(&name, &function.span));
}
functions.insert(name, asg_function);
}
let mut circuits = IndexMap::new();

View File

@ -25,13 +25,19 @@ use crate::*;
pub struct Canonicalizer {
// If we are in a circuit keep track of the circuit name.
circuit_name: Option<Identifier>,
in_circuit: bool,
}
impl Default for Canonicalizer {
fn default() -> Self {
Self {
circuit_name: None,
in_circuit: false,
}
}
}
impl Canonicalizer {
pub fn default() -> Self {
Self { circuit_name: None }
}
fn is_self_type(&mut self, type_option: Option<&Type>) -> bool {
matches!(type_option, Some(Type::SelfType))
}
@ -380,13 +386,15 @@ impl Canonicalizer {
}
impl ReconstructingReducer for Canonicalizer {
fn reduce_type(
&mut self,
_type_: &Type,
new: Type,
in_circuit: bool,
span: &Span,
) -> Result<Type, CanonicalizeError> {
fn in_circuit(&self) -> bool {
self.in_circuit
}
fn swap_in_circuit(&mut self) {
self.in_circuit = !self.in_circuit;
}
fn reduce_type(&mut self, _type_: &Type, new: Type, span: &Span) -> Result<Type, CanonicalizeError> {
match new {
Type::Array(type_, mut dimensions) => {
if dimensions.is_zero() {
@ -407,7 +415,7 @@ impl ReconstructingReducer for Canonicalizer {
Ok(array)
}
Type::SelfType if !in_circuit => Err(CanonicalizeError::big_self_outside_of_circuit(span)),
Type::SelfType if !self.in_circuit => Err(CanonicalizeError::big_self_outside_of_circuit(span)),
_ => Ok(new.clone()),
}
}
@ -416,7 +424,6 @@ impl ReconstructingReducer for Canonicalizer {
&mut self,
array_init: &ArrayInitExpression,
element: Expression,
_in_circuit: bool,
) -> Result<ArrayInitExpression, CanonicalizeError> {
if array_init.dimensions.is_zero() {
return Err(CanonicalizeError::invalid_array_dimension_size(&array_init.span));
@ -466,7 +473,6 @@ impl ReconstructingReducer for Canonicalizer {
assign: &AssignStatement,
assignee: Assignee,
value: Expression,
_in_circuit: bool,
) -> Result<AssignStatement, CanonicalizeError> {
match value {
Expression::Value(value_expr) if assign.operation != AssignOperation::Assign => {
@ -545,7 +551,6 @@ impl ReconstructingReducer for Canonicalizer {
input: Vec<FunctionInput>,
output: Option<Type>,
block: Block,
_in_circuit: bool,
) -> Result<Function, CanonicalizeError> {
let new_output = match output {
None => Some(Type::Tuple(vec![])),

View File

@ -22,15 +22,11 @@ use indexmap::IndexMap;
pub struct ReconstructingDirector<R: ReconstructingReducer> {
reducer: R,
in_circuit: bool,
}
impl<R: ReconstructingReducer> ReconstructingDirector<R> {
pub fn new(reducer: R) -> Self {
Self {
reducer,
in_circuit: false,
}
Self { reducer }
}
pub fn reduce_type(&mut self, type_: &Type, span: &Span) -> Result<Type, CanonicalizeError> {
@ -48,7 +44,7 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
_ => type_.clone(),
};
self.reducer.reduce_type(type_, new, self.in_circuit, span)
self.reducer.reduce_type(type_, new, span)
}
// Expressions
@ -84,7 +80,7 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
Expression::Call(call) => Expression::Call(self.reduce_call(&call)?),
};
self.reducer.reduce_expression(expression, new, self.in_circuit)
self.reducer.reduce_expression(expression, new)
}
pub fn reduce_identifier(&mut self, identifier: &Identifier) -> Result<Identifier, CanonicalizeError> {
@ -119,15 +115,13 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
let left = self.reduce_expression(&binary.left)?;
let right = self.reduce_expression(&binary.right)?;
self.reducer
.reduce_binary(binary, left, right, binary.op.clone(), self.in_circuit)
self.reducer.reduce_binary(binary, left, right, binary.op.clone())
}
pub fn reduce_unary(&mut self, unary: &UnaryExpression) -> Result<UnaryExpression, CanonicalizeError> {
let inner = self.reduce_expression(&unary.inner)?;
self.reducer
.reduce_unary(unary, inner, unary.op.clone(), self.in_circuit)
self.reducer.reduce_unary(unary, inner, unary.op.clone())
}
pub fn reduce_ternary(&mut self, ternary: &TernaryExpression) -> Result<TernaryExpression, CanonicalizeError> {
@ -135,15 +129,14 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
let if_true = self.reduce_expression(&ternary.if_true)?;
let if_false = self.reduce_expression(&ternary.if_false)?;
self.reducer
.reduce_ternary(ternary, condition, if_true, if_false, self.in_circuit)
self.reducer.reduce_ternary(ternary, condition, if_true, if_false)
}
pub fn reduce_cast(&mut self, cast: &CastExpression) -> Result<CastExpression, CanonicalizeError> {
let inner = self.reduce_expression(&cast.inner)?;
let target_type = self.reduce_type(&cast.target_type, &cast.span)?;
self.reducer.reduce_cast(cast, inner, target_type, self.in_circuit)
self.reducer.reduce_cast(cast, inner, target_type)
}
pub fn reduce_array_inline(
@ -164,8 +157,7 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
elements.push(reduced_element);
}
self.reducer
.reduce_array_inline(array_inline, elements, self.in_circuit)
self.reducer.reduce_array_inline(array_inline, elements)
}
pub fn reduce_array_init(
@ -174,7 +166,7 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
) -> Result<ArrayInitExpression, CanonicalizeError> {
let element = self.reduce_expression(&array_init.element)?;
self.reducer.reduce_array_init(array_init, element, self.in_circuit)
self.reducer.reduce_array_init(array_init, element)
}
pub fn reduce_array_access(
@ -184,8 +176,7 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
let array = self.reduce_expression(&array_access.array)?;
let index = self.reduce_expression(&array_access.index)?;
self.reducer
.reduce_array_access(array_access, array, index, self.in_circuit)
self.reducer.reduce_array_access(array_access, array, index)
}
pub fn reduce_array_range_access(
@ -205,7 +196,7 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
.transpose()?;
self.reducer
.reduce_array_range_access(array_range_access, array, left, right, self.in_circuit)
.reduce_array_range_access(array_range_access, array, left, right)
}
pub fn reduce_tuple_init(
@ -217,7 +208,7 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
elements.push(self.reduce_expression(element)?);
}
self.reducer.reduce_tuple_init(tuple_init, elements, self.in_circuit)
self.reducer.reduce_tuple_init(tuple_init, elements)
}
pub fn reduce_tuple_access(
@ -226,7 +217,7 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
) -> Result<TupleAccessExpression, CanonicalizeError> {
let tuple = self.reduce_expression(&tuple_access.tuple)?;
self.reducer.reduce_tuple_access(tuple_access, tuple, self.in_circuit)
self.reducer.reduce_tuple_access(tuple_access, tuple)
}
pub fn reduce_circuit_implied_variable_definition(
@ -241,7 +232,7 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
.transpose()?;
self.reducer
.reduce_circuit_implied_variable_definition(variable, identifier, expression, self.in_circuit)
.reduce_circuit_implied_variable_definition(variable, identifier, expression)
}
pub fn reduce_circuit_init(
@ -255,8 +246,7 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
members.push(self.reduce_circuit_implied_variable_definition(member)?);
}
self.reducer
.reduce_circuit_init(circuit_init, name, members, self.in_circuit)
self.reducer.reduce_circuit_init(circuit_init, name, members)
}
pub fn reduce_circuit_member_access(
@ -267,7 +257,7 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
let name = self.reduce_identifier(&circuit_member_access.name)?;
self.reducer
.reduce_circuit_member_access(circuit_member_access, circuit, name, self.in_circuit)
.reduce_circuit_member_access(circuit_member_access, circuit, name)
}
pub fn reduce_circuit_static_fn_access(
@ -278,7 +268,7 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
let name = self.reduce_identifier(&circuit_static_fn_access.name)?;
self.reducer
.reduce_circuit_static_fn_access(circuit_static_fn_access, circuit, name, self.in_circuit)
.reduce_circuit_static_fn_access(circuit_static_fn_access, circuit, name)
}
pub fn reduce_call(&mut self, call: &CallExpression) -> Result<CallExpression, CanonicalizeError> {
@ -289,7 +279,7 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
arguments.push(self.reduce_expression(argument)?);
}
self.reducer.reduce_call(call, function, arguments, self.in_circuit)
self.reducer.reduce_call(call, function, arguments)
}
// Statements
@ -305,14 +295,13 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
Statement::Block(block) => Statement::Block(self.reduce_block(&block)?),
};
self.reducer.reduce_statement(statement, new, self.in_circuit)
self.reducer.reduce_statement(statement, new)
}
pub fn reduce_return(&mut self, return_statement: &ReturnStatement) -> Result<ReturnStatement, CanonicalizeError> {
let expression = self.reduce_expression(&return_statement.expression)?;
self.reducer
.reduce_return(return_statement, expression, self.in_circuit)
self.reducer.reduce_return(return_statement, expression)
}
pub fn reduce_variable_name(&mut self, variable_name: &VariableName) -> Result<VariableName, CanonicalizeError> {
@ -338,8 +327,7 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
let value = self.reduce_expression(&definition.value)?;
self.reducer
.reduce_definition(definition, variable_names, type_, value, self.in_circuit)
self.reducer.reduce_definition(definition, variable_names, type_, value)
}
pub fn reduce_assignee_access(&mut self, access: &AssigneeAccess) -> Result<AssigneeAccess, CanonicalizeError> {
@ -355,7 +343,7 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
_ => access.clone(),
};
self.reducer.reduce_assignee_access(access, new, self.in_circuit)
self.reducer.reduce_assignee_access(access, new)
}
pub fn reduce_assignee(&mut self, assignee: &Assignee) -> Result<Assignee, CanonicalizeError> {
@ -366,15 +354,14 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
accesses.push(self.reduce_assignee_access(access)?);
}
self.reducer
.reduce_assignee(assignee, identifier, accesses, self.in_circuit)
self.reducer.reduce_assignee(assignee, identifier, accesses)
}
pub fn reduce_assign(&mut self, assign: &AssignStatement) -> Result<AssignStatement, CanonicalizeError> {
let assignee = self.reduce_assignee(&assign.assignee)?;
let value = self.reduce_expression(&assign.value)?;
self.reducer.reduce_assign(assign, assignee, value, self.in_circuit)
self.reducer.reduce_assign(assign, assignee, value)
}
pub fn reduce_conditional(
@ -389,8 +376,7 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
.map(|condition| self.reduce_statement(condition))
.transpose()?;
self.reducer
.reduce_conditional(conditional, condition, block, next, self.in_circuit)
self.reducer.reduce_conditional(conditional, condition, block, next)
}
pub fn reduce_iteration(
@ -402,8 +388,7 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
let stop = self.reduce_expression(&iteration.stop)?;
let block = self.reduce_block(&iteration.block)?;
self.reducer
.reduce_iteration(iteration, variable, start, stop, block, self.in_circuit)
self.reducer.reduce_iteration(iteration, variable, start, stop, block)
}
pub fn reduce_console(
@ -433,8 +418,7 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
}
};
self.reducer
.reduce_console(console_function_call, function, self.in_circuit)
self.reducer.reduce_console(console_function_call, function)
}
pub fn reduce_expression_statement(
@ -442,8 +426,7 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
expression: &ExpressionStatement,
) -> Result<ExpressionStatement, CanonicalizeError> {
let inner_expression = self.reduce_expression(&expression.expression)?;
self.reducer
.reduce_expression_statement(expression, inner_expression, self.in_circuit)
self.reducer.reduce_expression_statement(expression, inner_expression)
}
pub fn reduce_block(&mut self, block: &Block) -> Result<Block, CanonicalizeError> {
@ -452,7 +435,7 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
statements.push(self.reduce_statement(statement)?);
}
self.reducer.reduce_block(block, statements, self.in_circuit)
self.reducer.reduce_block(block, statements)
}
// Program
@ -468,9 +451,11 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
}
let mut circuits = IndexMap::new();
self.reducer.swap_in_circuit();
for (identifier, circuit) in program.circuits.iter() {
circuits.insert(self.reduce_identifier(identifier)?, self.reduce_circuit(circuit)?);
}
self.reducer.swap_in_circuit();
let mut functions = IndexMap::new();
for (identifier, function) in program.functions.iter() {
@ -488,8 +473,7 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
let identifier = self.reduce_identifier(&variable.identifier)?;
let type_ = self.reduce_type(&variable.type_, &variable.span)?;
self.reducer
.reduce_function_input_variable(variable, identifier, type_, self.in_circuit)
self.reducer.reduce_function_input_variable(variable, identifier, type_)
}
pub fn reduce_function_input(&mut self, input: &FunctionInput) -> Result<FunctionInput, CanonicalizeError> {
@ -500,7 +484,7 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
_ => input.clone(),
};
self.reducer.reduce_function_input(input, new, self.in_circuit)
self.reducer.reduce_function_input(input, new)
}
pub fn reduce_package_or_packages(
@ -533,7 +517,6 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
&mut self,
circuit_member: &CircuitMember,
) -> Result<CircuitMember, CanonicalizeError> {
self.in_circuit = !self.in_circuit;
let new = match circuit_member {
CircuitMember::CircuitVariable(identifier, type_) => CircuitMember::CircuitVariable(
self.reduce_identifier(&identifier)?,
@ -543,7 +526,6 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
CircuitMember::CircuitFunction(self.reduce_function(&function)?)
}
};
self.in_circuit = !self.in_circuit;
self.reducer.reduce_circuit_member(circuit_member, new)
}
@ -586,14 +568,7 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
let block = self.reduce_block(&function.block)?;
self.reducer.reduce_function(
function,
identifier,
annotations,
inputs,
output,
block,
self.in_circuit,
)
self.reducer
.reduce_function(function, identifier, annotations, inputs, output, block)
}
}

View File

@ -20,13 +20,10 @@ use indexmap::IndexMap;
// Needed to fix clippy bug.
#[allow(clippy::redundant_closure)]
pub trait ReconstructingReducer {
fn reduce_type(
&mut self,
_type_: &Type,
new: Type,
_in_circuit: bool,
_span: &Span,
) -> Result<Type, CanonicalizeError> {
fn in_circuit(&self) -> bool;
fn swap_in_circuit(&mut self);
fn reduce_type(&mut self, _type_: &Type, new: Type, _span: &Span) -> Result<Type, CanonicalizeError> {
Ok(new)
}
@ -35,7 +32,6 @@ pub trait ReconstructingReducer {
&mut self,
_expression: &Expression,
new: Expression,
_in_circuit: bool,
) -> Result<Expression, CanonicalizeError> {
Ok(new)
}
@ -77,7 +73,6 @@ pub trait ReconstructingReducer {
left: Expression,
right: Expression,
op: BinaryOperation,
_in_circuit: bool,
) -> Result<BinaryExpression, CanonicalizeError> {
Ok(BinaryExpression {
left: Box::new(left),
@ -92,7 +87,6 @@ pub trait ReconstructingReducer {
unary: &UnaryExpression,
inner: Expression,
op: UnaryOperation,
_in_circuit: bool,
) -> Result<UnaryExpression, CanonicalizeError> {
Ok(UnaryExpression {
inner: Box::new(inner),
@ -107,7 +101,6 @@ pub trait ReconstructingReducer {
condition: Expression,
if_true: Expression,
if_false: Expression,
_in_circuit: bool,
) -> Result<TernaryExpression, CanonicalizeError> {
Ok(TernaryExpression {
condition: Box::new(condition),
@ -122,7 +115,6 @@ pub trait ReconstructingReducer {
cast: &CastExpression,
inner: Expression,
target_type: Type,
_in_circuit: bool,
) -> Result<CastExpression, CanonicalizeError> {
Ok(CastExpression {
inner: Box::new(inner),
@ -135,7 +127,6 @@ pub trait ReconstructingReducer {
&mut self,
array_inline: &ArrayInlineExpression,
elements: Vec<SpreadOrExpression>,
_in_circuit: bool,
) -> Result<ArrayInlineExpression, CanonicalizeError> {
Ok(ArrayInlineExpression {
elements,
@ -147,7 +138,6 @@ pub trait ReconstructingReducer {
&mut self,
array_init: &ArrayInitExpression,
element: Expression,
_in_circuit: bool,
) -> Result<ArrayInitExpression, CanonicalizeError> {
Ok(ArrayInitExpression {
element: Box::new(element),
@ -161,7 +151,6 @@ pub trait ReconstructingReducer {
array_access: &ArrayAccessExpression,
array: Expression,
index: Expression,
_in_circuit: bool,
) -> Result<ArrayAccessExpression, CanonicalizeError> {
Ok(ArrayAccessExpression {
array: Box::new(array),
@ -176,7 +165,6 @@ pub trait ReconstructingReducer {
array: Expression,
left: Option<Expression>,
right: Option<Expression>,
_in_circuit: bool,
) -> Result<ArrayRangeAccessExpression, CanonicalizeError> {
Ok(ArrayRangeAccessExpression {
array: Box::new(array),
@ -190,7 +178,6 @@ pub trait ReconstructingReducer {
&mut self,
tuple_init: &TupleInitExpression,
elements: Vec<Expression>,
_in_circuit: bool,
) -> Result<TupleInitExpression, CanonicalizeError> {
Ok(TupleInitExpression {
elements,
@ -202,7 +189,6 @@ pub trait ReconstructingReducer {
&mut self,
tuple_access: &TupleAccessExpression,
tuple: Expression,
_in_circuit: bool,
) -> Result<TupleAccessExpression, CanonicalizeError> {
Ok(TupleAccessExpression {
tuple: Box::new(tuple),
@ -216,7 +202,6 @@ pub trait ReconstructingReducer {
_variable: &CircuitImpliedVariableDefinition,
identifier: Identifier,
expression: Option<Expression>,
_in_circuit: bool,
) -> Result<CircuitImpliedVariableDefinition, CanonicalizeError> {
Ok(CircuitImpliedVariableDefinition { identifier, expression })
}
@ -226,7 +211,6 @@ pub trait ReconstructingReducer {
circuit_init: &CircuitInitExpression,
name: Identifier,
members: Vec<CircuitImpliedVariableDefinition>,
_in_circuit: bool,
) -> Result<CircuitInitExpression, CanonicalizeError> {
Ok(CircuitInitExpression {
name,
@ -240,7 +224,6 @@ pub trait ReconstructingReducer {
circuit_member_access: &CircuitMemberAccessExpression,
circuit: Expression,
name: Identifier,
_in_circuit: bool,
) -> Result<CircuitMemberAccessExpression, CanonicalizeError> {
Ok(CircuitMemberAccessExpression {
circuit: Box::new(circuit),
@ -254,7 +237,6 @@ pub trait ReconstructingReducer {
circuit_static_fn_access: &CircuitStaticFunctionAccessExpression,
circuit: Expression,
name: Identifier,
_in_circuit: bool,
) -> Result<CircuitStaticFunctionAccessExpression, CanonicalizeError> {
Ok(CircuitStaticFunctionAccessExpression {
circuit: Box::new(circuit),
@ -268,7 +250,6 @@ pub trait ReconstructingReducer {
call: &CallExpression,
function: Expression,
arguments: Vec<Expression>,
_in_circuit: bool,
) -> Result<CallExpression, CanonicalizeError> {
Ok(CallExpression {
function: Box::new(function),
@ -278,12 +259,7 @@ pub trait ReconstructingReducer {
}
// Statements
fn reduce_statement(
&mut self,
_statement: &Statement,
new: Statement,
_in_circuit: bool,
) -> Result<Statement, CanonicalizeError> {
fn reduce_statement(&mut self, _statement: &Statement, new: Statement) -> Result<Statement, CanonicalizeError> {
Ok(new)
}
@ -291,7 +267,6 @@ pub trait ReconstructingReducer {
&mut self,
return_statement: &ReturnStatement,
expression: Expression,
_in_circuit: bool,
) -> Result<ReturnStatement, CanonicalizeError> {
Ok(ReturnStatement {
expression,
@ -317,7 +292,6 @@ pub trait ReconstructingReducer {
variable_names: Vec<VariableName>,
type_: Option<Type>,
value: Expression,
_in_circuit: bool,
) -> Result<DefinitionStatement, CanonicalizeError> {
Ok(DefinitionStatement {
declaration_type: definition.declaration_type.clone(),
@ -332,7 +306,6 @@ pub trait ReconstructingReducer {
&mut self,
_access: &AssigneeAccess,
new: AssigneeAccess,
_in_circuit: bool,
) -> Result<AssigneeAccess, CanonicalizeError> {
Ok(new)
}
@ -342,7 +315,6 @@ pub trait ReconstructingReducer {
assignee: &Assignee,
identifier: Identifier,
accesses: Vec<AssigneeAccess>,
_in_circuit: bool,
) -> Result<Assignee, CanonicalizeError> {
Ok(Assignee {
identifier,
@ -356,7 +328,6 @@ pub trait ReconstructingReducer {
assign: &AssignStatement,
assignee: Assignee,
value: Expression,
_in_circuit: bool,
) -> Result<AssignStatement, CanonicalizeError> {
Ok(AssignStatement {
operation: assign.operation.clone(),
@ -372,7 +343,6 @@ pub trait ReconstructingReducer {
condition: Expression,
block: Block,
statement: Option<Statement>,
_in_circuit: bool,
) -> Result<ConditionalStatement, CanonicalizeError> {
Ok(ConditionalStatement {
condition,
@ -389,7 +359,6 @@ pub trait ReconstructingReducer {
start: Expression,
stop: Expression,
block: Block,
_in_circuit: bool,
) -> Result<IterationStatement, CanonicalizeError> {
Ok(IterationStatement {
variable,
@ -404,7 +373,6 @@ pub trait ReconstructingReducer {
&mut self,
console: &ConsoleStatement,
function: ConsoleFunction,
_in_circuit: bool,
) -> Result<ConsoleStatement, CanonicalizeError> {
Ok(ConsoleStatement {
function,
@ -416,7 +384,6 @@ pub trait ReconstructingReducer {
&mut self,
expression_statement: &ExpressionStatement,
expression: Expression,
_in_circuit: bool,
) -> Result<ExpressionStatement, CanonicalizeError> {
Ok(ExpressionStatement {
expression,
@ -424,12 +391,7 @@ pub trait ReconstructingReducer {
})
}
fn reduce_block(
&mut self,
block: &Block,
statements: Vec<Statement>,
_in_circuit: bool,
) -> Result<Block, CanonicalizeError> {
fn reduce_block(&mut self, block: &Block, statements: Vec<Statement>) -> Result<Block, CanonicalizeError> {
Ok(Block {
statements,
span: block.span.clone(),
@ -459,7 +421,6 @@ pub trait ReconstructingReducer {
variable: &FunctionInputVariable,
identifier: Identifier,
type_: Type,
_in_circuit: bool,
) -> Result<FunctionInputVariable, CanonicalizeError> {
Ok(FunctionInputVariable {
identifier,
@ -474,7 +435,6 @@ pub trait ReconstructingReducer {
&mut self,
_input: &FunctionInput,
new: FunctionInput,
_in_circuit: bool,
) -> Result<FunctionInput, CanonicalizeError> {
Ok(new)
}
@ -536,7 +496,6 @@ pub trait ReconstructingReducer {
input: Vec<FunctionInput>,
output: Option<Type>,
block: Block,
_in_circuit: bool,
) -> Result<Function, CanonicalizeError> {
Ok(Function {
identifier,

View File

@ -53,27 +53,27 @@ version = "1.2.3"
version = "0.4"
[dependencies.snarkvm-curves]
version = "0.2.1"
version = "0.2.2"
default-features = false
[dependencies.snarkvm-fields]
version = "0.2.1"
version = "0.2.2"
default-features = false
[dependencies.snarkvm-dpc]
version = "0.2.1"
version = "0.2.2"
default-features = false
[dependencies.snarkvm-gadgets]
version = "0.2.1"
version = "0.2.2"
default-features = false
[dependencies.snarkvm-r1cs]
version = "0.2.1"
version = "0.2.2"
default-features = false
[dependencies.snarkvm-utilities]
version = "0.2.1"
version = "0.2.2"
[dependencies.bincode]
version = "1.3"
@ -114,7 +114,7 @@ version = "0.3"
default-features = false
[dev-dependencies.snarkvm-algorithms]
version = "0.2.1"
version = "0.2.2"
default-features = false
[dev-dependencies.tempfile]

View File

@ -16,7 +16,7 @@
use leo_ast::{FormattedError, LeoError, Span};
use snarkvm_gadgets::errors::SignedIntegerError;
use snarkvm_gadgets::errors::{SignedIntegerError, UnsignedIntegerError};
use snarkvm_r1cs::SynthesisError;
#[derive(Debug, Error)]
@ -38,6 +38,15 @@ impl IntegerError {
Self::new_from_span(message, span)
}
pub fn unsigned(error: UnsignedIntegerError, span: &Span) -> Self {
let message = format!(
"integer operation failed due to the unsigned integer error `{:?}`",
error
);
Self::new_from_span(message, span)
}
pub fn synthesis(error: SynthesisError, span: &Span) -> Self {
let message = format!("integer operation failed due to the synthesis error `{}`", error);

View File

@ -98,16 +98,11 @@ use tendril::StrTendril;
pub struct CombineAstAsgDirector<R: ReconstructingReducer> {
ast_reducer: R,
options: CompilerOptions,
in_circuit: bool,
}
impl<R: ReconstructingReducer> CombineAstAsgDirector<R> {
pub fn new(ast_reducer: R, options: CompilerOptions) -> Self {
Self {
ast_reducer,
options,
in_circuit: false,
}
Self { ast_reducer, options }
}
pub fn reduce_type(&mut self, ast: &AstType, asg: &AsgType, span: &Span) -> Result<AstType, CanonicalizeError> {
@ -138,7 +133,7 @@ impl<R: ReconstructingReducer> CombineAstAsgDirector<R> {
_ => ast.clone(),
};
self.ast_reducer.reduce_type(ast, new, self.in_circuit, span)
self.ast_reducer.reduce_type(ast, new, span)
}
pub fn reduce_expression(
@ -197,7 +192,7 @@ impl<R: ReconstructingReducer> CombineAstAsgDirector<R> {
_ => ast.clone(),
};
self.ast_reducer.reduce_expression(ast, new, self.in_circuit)
self.ast_reducer.reduce_expression(ast, new)
}
pub fn reduce_array_access(
@ -208,7 +203,7 @@ impl<R: ReconstructingReducer> CombineAstAsgDirector<R> {
let array = self.reduce_expression(&ast.array, asg.array.get())?;
let index = self.reduce_expression(&ast.index, asg.index.get())?;
self.ast_reducer.reduce_array_access(ast, array, index, self.in_circuit)
self.ast_reducer.reduce_array_access(ast, array, index)
}
pub fn reduce_array_init(
@ -218,7 +213,7 @@ impl<R: ReconstructingReducer> CombineAstAsgDirector<R> {
) -> Result<AstArrayInitExpression, CanonicalizeError> {
let element = self.reduce_expression(&ast.element, asg.element.get())?;
self.ast_reducer.reduce_array_init(ast, element, self.in_circuit)
self.ast_reducer.reduce_array_init(ast, element)
}
pub fn reduce_array_inline(
@ -240,7 +235,7 @@ impl<R: ReconstructingReducer> CombineAstAsgDirector<R> {
elements.push(reduced_element);
}
self.ast_reducer.reduce_array_inline(ast, elements, self.in_circuit)
self.ast_reducer.reduce_array_inline(ast, elements)
}
pub fn reduce_array_range_access(
@ -258,8 +253,7 @@ impl<R: ReconstructingReducer> CombineAstAsgDirector<R> {
_ => None,
};
self.ast_reducer
.reduce_array_range_access(ast, array, left, right, self.in_circuit)
self.ast_reducer.reduce_array_range_access(ast, array, left, right)
}
pub fn reduce_binary(
@ -270,8 +264,7 @@ impl<R: ReconstructingReducer> CombineAstAsgDirector<R> {
let left = self.reduce_expression(&ast.left, asg.left.get())?;
let right = self.reduce_expression(&ast.right, asg.right.get())?;
self.ast_reducer
.reduce_binary(ast, left, right, ast.op.clone(), self.in_circuit)
self.ast_reducer.reduce_binary(ast, left, right, ast.op.clone())
}
pub fn reduce_call(
@ -289,8 +282,7 @@ impl<R: ReconstructingReducer> CombineAstAsgDirector<R> {
arguments.push(self.reduce_expression(ast_arg, asg_arg.get())?);
}
self.ast_reducer
.reduce_call(ast, *ast.function.clone(), arguments, self.in_circuit)
self.ast_reducer.reduce_call(ast, *ast.function.clone(), arguments)
}
pub fn reduce_cast(
@ -301,7 +293,7 @@ impl<R: ReconstructingReducer> CombineAstAsgDirector<R> {
let inner = self.reduce_expression(&ast.inner, &asg.inner.get())?;
let target_type = self.reduce_type(&ast.target_type, &asg.target_type, &ast.span)?;
self.ast_reducer.reduce_cast(ast, inner, target_type, self.in_circuit)
self.ast_reducer.reduce_cast(ast, inner, target_type)
}
pub fn reduce_constant(
@ -333,7 +325,7 @@ impl<R: ReconstructingReducer> CombineAstAsgDirector<R> {
// does it matter?
self.ast_reducer
.reduce_circuit_member_access(ast, *ast.circuit.clone(), ast.name.clone(), self.in_circuit)
.reduce_circuit_member_access(ast, *ast.circuit.clone(), ast.name.clone())
}
pub fn reduce_circuit_static_fn_access(
@ -348,7 +340,7 @@ impl<R: ReconstructingReducer> CombineAstAsgDirector<R> {
// does it matter?
self.ast_reducer
.reduce_circuit_static_fn_access(ast, *ast.circuit.clone(), ast.name.clone(), self.in_circuit)
.reduce_circuit_static_fn_access(ast, *ast.circuit.clone(), ast.name.clone())
}
pub fn reduce_circuit_implied_variable_definition(
@ -362,12 +354,8 @@ impl<R: ReconstructingReducer> CombineAstAsgDirector<R> {
.map(|ast_expr| self.reduce_expression(ast_expr, asg))
.transpose()?;
self.ast_reducer.reduce_circuit_implied_variable_definition(
ast,
ast.identifier.clone(),
expression,
self.in_circuit,
)
self.ast_reducer
.reduce_circuit_implied_variable_definition(ast, ast.identifier.clone(), expression)
}
pub fn reduce_circuit_init(
@ -380,8 +368,7 @@ impl<R: ReconstructingReducer> CombineAstAsgDirector<R> {
members.push(self.reduce_circuit_implied_variable_definition(ast_member, asg_member.1.get())?);
}
self.ast_reducer
.reduce_circuit_init(ast, ast.name.clone(), members, self.in_circuit)
self.ast_reducer.reduce_circuit_init(ast, ast.name.clone(), members)
}
pub fn reduce_ternary(
@ -393,8 +380,7 @@ impl<R: ReconstructingReducer> CombineAstAsgDirector<R> {
let if_true = self.reduce_expression(&ast.if_true, asg.if_true.get())?;
let if_false = self.reduce_expression(&ast.if_false, asg.if_false.get())?;
self.ast_reducer
.reduce_ternary(ast, condition, if_true, if_false, self.in_circuit)
self.ast_reducer.reduce_ternary(ast, condition, if_true, if_false)
}
pub fn reduce_tuple_access(
@ -404,7 +390,7 @@ impl<R: ReconstructingReducer> CombineAstAsgDirector<R> {
) -> Result<AstTupleAccessExpression, CanonicalizeError> {
let tuple = self.reduce_expression(&ast.tuple, asg.tuple_ref.get())?;
self.ast_reducer.reduce_tuple_access(ast, tuple, self.in_circuit)
self.ast_reducer.reduce_tuple_access(ast, tuple)
}
pub fn reduce_tuple_init(
@ -418,7 +404,7 @@ impl<R: ReconstructingReducer> CombineAstAsgDirector<R> {
elements.push(element);
}
self.ast_reducer.reduce_tuple_init(ast, elements, self.in_circuit)
self.ast_reducer.reduce_tuple_init(ast, elements)
}
pub fn reduce_unary(
@ -428,8 +414,7 @@ impl<R: ReconstructingReducer> CombineAstAsgDirector<R> {
) -> Result<AstUnaryExpression, CanonicalizeError> {
let inner = self.reduce_expression(&ast.inner, asg.inner.get())?;
self.ast_reducer
.reduce_unary(ast, inner, ast.op.clone(), self.in_circuit)
self.ast_reducer.reduce_unary(ast, inner, ast.op.clone())
}
pub fn reduce_variable_ref(
@ -480,7 +465,7 @@ impl<R: ReconstructingReducer> CombineAstAsgDirector<R> {
_ => ast_statement.clone(),
};
self.ast_reducer.reduce_statement(ast_statement, new, self.in_circuit)
self.ast_reducer.reduce_statement(ast_statement, new)
}
pub fn reduce_assign_access(
@ -508,7 +493,7 @@ impl<R: ReconstructingReducer> CombineAstAsgDirector<R> {
_ => ast.clone(),
};
self.ast_reducer.reduce_assignee_access(ast, new, self.in_circuit)
self.ast_reducer.reduce_assignee_access(ast, new)
}
pub fn reduce_assignee(&mut self, ast: &Assignee, asg: &[AsgAssignAccess]) -> Result<Assignee, CanonicalizeError> {
@ -517,8 +502,7 @@ impl<R: ReconstructingReducer> CombineAstAsgDirector<R> {
accesses.push(self.reduce_assign_access(ast_access, asg_access)?);
}
self.ast_reducer
.reduce_assignee(ast, ast.identifier.clone(), accesses, self.in_circuit)
self.ast_reducer.reduce_assignee(ast, ast.identifier.clone(), accesses)
}
pub fn reduce_assign(
@ -529,7 +513,7 @@ impl<R: ReconstructingReducer> CombineAstAsgDirector<R> {
let assignee = self.reduce_assignee(&ast.assignee, &asg.target_accesses)?;
let value = self.reduce_expression(&ast.value, asg.value.get())?;
self.ast_reducer.reduce_assign(ast, assignee, value, self.in_circuit)
self.ast_reducer.reduce_assign(ast, assignee, value)
}
pub fn reduce_block(
@ -542,7 +526,7 @@ impl<R: ReconstructingReducer> CombineAstAsgDirector<R> {
statements.push(self.reduce_statement(ast_statement, asg_statement.get())?);
}
self.ast_reducer.reduce_block(ast, statements, self.in_circuit)
self.ast_reducer.reduce_block(ast, statements)
}
pub fn reduce_conditional(
@ -563,8 +547,7 @@ impl<R: ReconstructingReducer> CombineAstAsgDirector<R> {
_ => None,
};
self.ast_reducer
.reduce_conditional(ast, condition, block, next, self.in_circuit)
self.ast_reducer.reduce_conditional(ast, condition, block, next)
}
pub fn reduce_console(
@ -600,7 +583,7 @@ impl<R: ReconstructingReducer> CombineAstAsgDirector<R> {
_ => ast.function.clone(),
};
self.ast_reducer.reduce_console(ast, function, self.in_circuit)
self.ast_reducer.reduce_console(ast, function)
}
pub fn reduce_definition(
@ -638,7 +621,7 @@ impl<R: ReconstructingReducer> CombineAstAsgDirector<R> {
let value = self.reduce_expression(&ast.value, asg.value.get())?;
self.ast_reducer
.reduce_definition(ast, ast.variable_names.clone(), type_, value, self.in_circuit)
.reduce_definition(ast, ast.variable_names.clone(), type_, value)
}
pub fn reduce_expression_statement(
@ -647,8 +630,7 @@ impl<R: ReconstructingReducer> CombineAstAsgDirector<R> {
asg: &AsgExpressionStatement,
) -> Result<AstExpressionStatement, CanonicalizeError> {
let inner_expression = self.reduce_expression(&ast.expression, asg.expression.get())?;
self.ast_reducer
.reduce_expression_statement(ast, inner_expression, self.in_circuit)
self.ast_reducer.reduce_expression_statement(ast, inner_expression)
}
pub fn reduce_iteration(
@ -666,7 +648,7 @@ impl<R: ReconstructingReducer> CombineAstAsgDirector<R> {
}
self.ast_reducer
.reduce_iteration(ast, ast.variable.clone(), start, stop, block, self.in_circuit)
.reduce_iteration(ast, ast.variable.clone(), start, stop, block)
}
pub fn reduce_return(
@ -676,7 +658,7 @@ impl<R: ReconstructingReducer> CombineAstAsgDirector<R> {
) -> Result<AstReturnStatement, CanonicalizeError> {
let expression = self.reduce_expression(&ast.expression, asg.expression.get())?;
self.ast_reducer.reduce_return(ast, expression, self.in_circuit)
self.ast_reducer.reduce_return(ast, expression)
}
pub fn reduce_program(
@ -684,10 +666,12 @@ impl<R: ReconstructingReducer> CombineAstAsgDirector<R> {
ast: &leo_ast::Program,
asg: &leo_asg::Program,
) -> Result<leo_ast::Program, leo_ast::CanonicalizeError> {
self.ast_reducer.swap_in_circuit();
let mut circuits = IndexMap::new();
for ((ast_ident, ast_circuit), (_asg_ident, asg_circuit)) in ast.circuits.iter().zip(&asg.circuits) {
circuits.insert(ast_ident.clone(), self.reduce_circuit(ast_circuit, asg_circuit)?);
}
self.ast_reducer.swap_in_circuit();
let mut functions = IndexMap::new();
for ((ast_ident, ast_function), (_asg_ident, asg_function)) in ast.functions.iter().zip(&asg.functions) {
@ -729,7 +713,6 @@ impl<R: ReconstructingReducer> CombineAstAsgDirector<R> {
ast.input.clone(),
output,
block,
self.in_circuit,
)
}
@ -738,7 +721,6 @@ impl<R: ReconstructingReducer> CombineAstAsgDirector<R> {
ast: &AstCircuitMember,
asg: &AsgCircuitMember,
) -> Result<AstCircuitMember, CanonicalizeError> {
self.in_circuit = !self.in_circuit;
let new = match (ast, asg) {
(AstCircuitMember::CircuitVariable(identifier, ast_type), AsgCircuitMember::Variable(asg_type)) => {
AstCircuitMember::CircuitVariable(
@ -751,7 +733,6 @@ impl<R: ReconstructingReducer> CombineAstAsgDirector<R> {
}
_ => ast.clone(),
};
self.in_circuit = !self.in_circuit;
self.ast_reducer.reduce_circuit_member(ast, new)
}

View File

@ -23,6 +23,7 @@ use crate::{
GroupType,
IndicatorAndConstrainedValue,
Integer,
IntegerTrait,
StatementResult,
};
use leo_asg::IterationStatement;

View File

@ -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::{errors::AddressError, ConstrainedValue, GroupType};
use crate::{errors::AddressError, ConstrainedValue, GroupType, IntegerTrait};
use leo_ast::{InputValue, Span};
use snarkvm_dpc::{account::AccountAddress, base_dpc::instantiated::Components};
@ -24,7 +24,7 @@ use snarkvm_gadgets::traits::utilities::{
boolean::Boolean,
eq::{ConditionalEqGadget, EqGadget, EvaluateEqGadget},
select::CondSelectGadget,
uint::{UInt, UInt8},
uint::UInt8,
};
use snarkvm_r1cs::{Assignment, ConstraintSystem, SynthesisError};
use snarkvm_utilities::ToBytes;

View File

@ -28,10 +28,10 @@ use snarkvm_gadgets::traits::utilities::{
eq::{ConditionalEqGadget, EqGadget, EvaluateEqGadget},
int::{Int128, Int16, Int32, Int64, Int8},
select::CondSelectGadget,
uint::*,
uint::{Sub as UIntSub, *},
};
use snarkvm_r1cs::{ConstraintSystem, SynthesisError};
use std::fmt;
use std::{convert::TryInto, fmt};
/// An integer type enum wrapping the integer value.
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd)]
@ -83,7 +83,7 @@ impl Integer {
pub fn get_bits(&self) -> Vec<Boolean> {
let integer = self;
match_integer!(integer => integer.get_bits())
match_integer!(integer => integer.to_bits_le())
}
// pub fn get_bits_typed(&self) -> (Vec<Boolean>, IntegerType) {
@ -113,7 +113,7 @@ impl Integer {
pub fn to_usize(&self) -> Option<usize> {
let unsigned_integer = self;
match_unsigned_integer!(unsigned_integer => unsigned_integer.get_index())
match_unsigned_integer!(unsigned_integer => unsigned_integer.value.map(|num| num.try_into().ok()).flatten())
}
pub fn get_type(&self) -> IntegerType {

View File

@ -14,41 +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 snarkvm_gadgets::traits::utilities::{
boolean::Boolean,
int::{Int128, Int16, Int32, Int64, Int8},
uint::{UInt128, UInt16, UInt32, UInt64, UInt8},
};
use std::{convert::TryInto, fmt::Debug};
pub trait IntegerTrait: Sized + Clone + Debug {
fn get_value(&self) -> Option<String>;
fn get_index(&self) -> Option<usize>;
fn get_bits(&self) -> Vec<Boolean>;
}
macro_rules! integer_trait_impl {
($($gadget: ident)*) => ($(
impl IntegerTrait for $gadget {
fn get_value(&self) -> Option<String> {
self.value.map(|num| num.to_string())
}
fn get_index(&self) -> Option<usize> {
self.value.map(|num| num.try_into().ok()).flatten()
}
fn get_bits(&self) -> Vec<Boolean> {
self.bits.clone()
}
}
)*)
}
integer_trait_impl!(UInt8 UInt16 UInt32 UInt64 UInt128 Int8 Int16 Int32 Int64 Int128);
pub use snarkvm_gadgets::traits::utilities::integer::Integer as IntegerTrait;
/// Useful macros to avoid duplicating `match` constructions.
#[macro_export]
@ -125,19 +91,19 @@ macro_rules! match_integers_span {
(($a: ident, $b: ident), $span: ident => $expression:expr) => {
match ($a, $b) {
(Integer::U8($a), Integer::U8($b)) => {
Some(Integer::U8($expression.map_err(|e| IntegerError::synthesis(e, $span))?))
Some(Integer::U8($expression.map_err(|e| IntegerError::unsigned(e, $span))?))
}
(Integer::U16($a), Integer::U16($b)) => {
Some(Integer::U16($expression.map_err(|e| IntegerError::unsigned(e, $span))?))
}
(Integer::U32($a), Integer::U32($b)) => {
Some(Integer::U32($expression.map_err(|e| IntegerError::unsigned(e, $span))?))
}
(Integer::U64($a), Integer::U64($b)) => {
Some(Integer::U64($expression.map_err(|e| IntegerError::unsigned(e, $span))?))
}
(Integer::U16($a), Integer::U16($b)) => Some(Integer::U16(
$expression.map_err(|e| IntegerError::synthesis(e, $span))?,
)),
(Integer::U32($a), Integer::U32($b)) => Some(Integer::U32(
$expression.map_err(|e| IntegerError::synthesis(e, $span))?,
)),
(Integer::U64($a), Integer::U64($b)) => Some(Integer::U64(
$expression.map_err(|e| IntegerError::synthesis(e, $span))?,
)),
(Integer::U128($a), Integer::U128($b)) => Some(Integer::U128(
$expression.map_err(|e| IntegerError::synthesis(e, $span))?,
$expression.map_err(|e| IntegerError::unsigned(e, $span))?,
)),
(Integer::I8($a), Integer::I8($b)) => {

View File

@ -0,0 +1,7 @@
function main() {
console.log("{}", 1u8);
}
function main() {
console.log("{}", 2u8);
}

View File

@ -211,3 +211,11 @@ fn test_array_params_direct_call() {
assert_satisfied(program);
}
#[test]
fn test_duplicate_function_definition() {
let program_string = include_str!("duplicate_definition.leo");
let error = parse_program(program_string).err().unwrap();
expect_asg_error(error);
}

View File

@ -14,5 +14,5 @@ keywords = [
]
[dependencies]
abnf = "0.10.1"
abnf = "0.10.2"
anyhow = "1.0"

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,6 @@
; Leo Library
;
; Copyright (C) 2021 Aleo Systems Inc.
;
; Author: Alessandro Coglio (acoglio on GitHub)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -20,7 +18,7 @@
; Note that this CR LF requirement only applies to the grammar files themselves.
; It does not apply to the lines of the languages described by the grammar.
; ABNF grammar may describe any kinds of languages,
; ABNF grammars may describe any kind of languages,
; with any kind of line terminators,
; or even without line terminators at all (e.g. for "binary" languages).
@ -29,29 +27,23 @@
; Introduction
; ------------
; This file contains an initial draft of
; a complete ABNF (Augmented Backus-Naur Form) grammar of Leo.
; This file contains an ABNF (Augmented Backus-Naur Form) grammar of Leo.
; Background on ABNF is provided later in this file.
; The initial motivation for creating an ABNF grammar of Leo was that
; we have a formally verified parser of ABNF grammars
; This grammar provides an official definition of the syntax of Leo
; that is both human-readable and machine-readable.
; It will be part of an upcoming Leo language reference.
; It may also be used to generate parser tests at some point.
; We are also using this grammar
; as part of a mathematical formalization of the Leo language,
; which we are developing in the ACL2 theorem prover
; and which we plan to publish at some point.
; In particular, we have used a formally verified parser of ABNF grammars
; (at https://github.com/acl2/acl2/tree/master/books/kestrel/abnf;
; also see the paper at https://www.kestrel.edu/people/coglio/vstte18.pdf)
; which we have used to parse this ABNF grammar of Leo
; into a formal representation, in the ACL2 theorem prover,
; of the Leo concrete syntax.
; The parsing of this grammar file into an ACL2 representation
; happens every time the ACL2 formalization of Leo is built.
; In addition to that initial motivation,
; this ABNF grammar has now the additional and primary purpose of
; providing an official definition of the syntax of Leo
; that is both human-readable and machine-readable.
; This grammar will be part of the (upcoming) Leo language reference,
; of the Leo Language Formal Specification
; (i.e. the LaTeX document in the leo-semantics repo),
; and of the ACL2 formalization of Leo (which was the initial motivation).
; It has also been suggested that it may be used to generate tests.
; to parse this grammar into a formal representation of the Leo concrete syntax
; and to validate that the grammar satisfies certain consistency properties.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -59,13 +51,10 @@
; ------------------
; ABNF is an Internet standard:
; see https://www.rfc-editor.org/info/rfc5234
; and https://www.rfc-editor.org/info/rfc7405.
; see RFC 5234 at https://www.rfc-editor.org/info/rfc5234
; and RFC 7405 at https://www.rfc-editor.org/info/rfc7405.
; It is used to specify the syntax of JSON, HTTP, and other standards.
; The following is copied (and "un-LaTeX'd") from the aforementioned paper
; (at https://www.kestrel.edu/people/coglio/vstte18.pdf).
; ABNF adds conveniences and makes slight modifications
; to Backus-Naur Form (BNF),
; without going beyond context-free grammars.
@ -82,15 +71,15 @@
; and denotes them via:
; (i) binary, decimal, or hexadecimal sequences,
; e.g. %b1.11.1010, %d1.3.10, and %x.1.3.A
; all denote the string '1 3 10';
; all denote the sequence of terminals '1 3 10';
; (ii) binary, decimal, or hexadecimal ranges,
; e.g. %x30-39 denotes any string 'n' with 48 <= n <= 57
; (an ASCII digit);
; e.g. %x30-39 denotes any singleton sequence of terminals
; 'n' with 48 <= n <= 57 (an ASCII digit);
; (iii) case-sensitive ASCII strings,
; e.g. %s"Ab" denotes the string '65 98';
; e.g. %s"Ab" denotes the sequence of terminals '65 98';
; and (iv) case-insensitive ASCII strings,
; e.g. %i"ab", or just "ab", denotes
; any string among
; any sequence of terminals among
; '65 66',
; '65 98',
; '97 66', and
@ -114,7 +103,7 @@
; Repetition prefixes have precedence over juxtapositions,
; which have precedence over /.
; Round brackets group things and override the aforementioned precedence rules,
; e.g. *(WSP / CRLF WSP) denotes strings
; e.g. *(WSP / CRLF WSP) denotes sequences of terminals
; obtained by repeating, zero or more times,
; either (i) a WSP or (ii) a CRLF followed by a WSP.
; Square brackets also group things but make them optional,
@ -141,49 +130,42 @@
; Structure
; ---------
; Language specifications often define the syntax of their languages via
; This ABNF grammar consists of two (sub-)grammars:
; (i) a lexical grammar that describes how
; sequence of characters are parsed into tokens, and
; (ii) a syntactic grammar that described how
; tokens are parsed into expressions, statements, etc.
; (The adjectives 'lexical' and 'syntactic' are
; the ones used in the Java language specification;
; other terms may be used by other languages,
; but the essence is similar.)
; The situation is sometimes more complex,
; with multiple passes (e.g. Unicode escape processing in Java),
; but the division between lexical and syntactic (in the sense above) stands.
; The adjectives 'lexical' and 'syntactic' are
; the same ones used in the Java language reference,
; for instance;
; alternative terms may be used in other languages,
; but the separation into these two components is quite common
; (the situation is sometimes a bit more complex, with multiple passes,
; e.g. Unicode escape processing in Java).
; In the aforementioned language specifications,
; both the lexical and syntactic grammars
; are normally written in a context-free grammar notation,
; augmented with natural language that may assert, for instance,
; that tokenization always takes the longest sequence that constitutes a token.
; This dual structure appears to be motivated by the fact that
; This separation enables
; concerns of white space, line endings, etc.
; can be handled by the lexical grammar,
; allowing the syntactic grammar to focus on the more important structure.
; Handling both aspects in a single context-free grammar may be unwieldy,
; to be handled by the lexical grammar,
; with the syntactic grammar focused on the more important structure.
; Handling both aspects in a single grammar may be unwieldy,
; so having two grammars provides more clarity and readability.
; In contrast, PEG (Parsing Expression Grammar) formalisms like Pest
; naturally embody a procedural interpretation
; that can handle white space and tokenization in just one manageable grammar.
; However, this procedural interpretaion may be sometimes
; less clear and readable to humans than context-free rules.
; Indeed, context-free grammar are commonly used to documentat languages.
; ABNF is a context-free grammar notation,
; with no procedural interpretation,
; and therefore it makes sense to define
; separate lexical and syntactic ABNF grammars for Leo.
; Conceptually, the two grammars define two subsequent processing phases,
; ABNF is a context-free grammar notation, with no procedural interpretation.
; The two grammars conceptually define two subsequent processing phases,
; as detailed below.
; However, a parser implementation does not need to perform
; two strictly separate phases (in fact, it typically does not),
; so long as it produces the same final result.
; The grammar is accompanied by some extra-grammatical requirements,
; which are not conveniently expressible in a context-free grammar like ABNF.
; These requirements are needed to make the grammar unambiguous,
; i.e. to ensure that, for each sequence of terminals,
; there is exactly one parse tree for that sequence terminals
; that satisfies not only the grammar rules
; but also the extra-grammatical requirements.
; These requirements are expressed as comments in this file.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Operator Precedence
@ -205,8 +187,9 @@
; / additive-expression "+" multiplicative-expression
; / additive-expression "-" multiplicative-expression
;
; this rule tells us that the additive operators '+' and '-' have
; lower precedence than the multiplicative operators '*' and '/',
; These rules tell us
; that the additive operators '+' and '-' have lower precedence
; than the multiplicative operators '*' and '/',
; and that both the additive and multiplicative operators associate to the left.
; This may be best understood via the examples given below.
@ -261,14 +244,14 @@
; Naming Convention
; -----------------
; For this ABNF grammar, we choose nonterminal names
; This ABNF grammar uses nonterminal names
; that consist of complete English words, separated by dashes,
; and that describe the construct the way it is in English.
; For instance, we use the name 'conditional-statement'
; to describe conditional statements.
; At the same time, we attempt to establish
; a precise and "official" nomenclature for the Leo constructs,
; At the same time, this grammar establishes
; a precise and official nomenclature for the Leo constructs,
; by way of the nonterminal names that define their syntax.
; For instance, the rule
;
@ -286,19 +269,21 @@
; is the fact that, as discussed above,
; we write the grammar rules in a way that determines
; the relative precedence and the associativity of expression operators,
; and that therefore we have rules like
; and therefore we have rules like
;
; unary-expression = primary-expression
; / "!" unary-expression
; / "-" unary-expression
;
; In order to allow the recursion of the rule to stop,
; we need to regard, in the grammar, a primary expression as a unary expression.
; we need to regard, in the grammar, a primary expression as a unary expression
; (i.e. a primary expression is also a unary expression in the grammar;
; but note that the opposite is not true).
; However, this is just a grammatical artifact:
; ontologically, a primary expression is not really a unary expression,
; because a unary expression is one that consists of
; a unary operator and an operand sub-expression.
; These terminological "exceptions" should be easy to identify in the rules.
; These terminological exceptions should be easy to identify in the rules.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -310,11 +295,12 @@
; which are numbers in the range form 0 to 10FFFFh.
; These are captured by the ABNF rule 'character' below.
; The lexical grammar defines how, conceptually,
; The lexical grammar defines how, at least conceptually,
; the sequence of characters is turned into
; a sequence of tokens, comments, and whitespaces.
; a sequence of tokens, comments, and whitespaces:
; these entities are all defined by the grammar rules below.
; As stated, the lexical grammar is ambiguous.
; As stated, the lexical grammar alone is ambiguous.
; For example, the sequence of characters '**' (i.e. two stars)
; could be equally parsed as two '*' symbol tokens or one '**' symbol token
; (see rule for 'symbol' below).
@ -329,10 +315,6 @@
; the longest possible sequence of characters is always parsed.
; This way, '**' must be parsed as one '**' symbol token,
; and '<CR><LF>' must be parsed as one line terminator.
; (We should formalize this requirement,
; along with the other extra-grammatical requirements given below,
; and formally prove that they indeed make
; the lexical grammar of Leo unambiguous.)
; As mentioned above, a character is any Unicode code point.
; This grammar does not say how those are encoded in files (e.g. UTF-8):
@ -371,7 +353,8 @@ not-star-or-slash = %x0-29 / %x2B-2E / %x30-10FFFF ; anything but * or /
; a line feed,
; or a carriage return immediately followed by a line feed.
; Note that the latter combination constitutes a single line terminator,
; according to the extra-grammatical rule of the longest sequence.
; according to the extra-grammatical requirement of the longest sequence,
; described above.
newline = line-feed / carriage-return / carriage-return line-feed
@ -381,13 +364,13 @@ whitespace = space / horizontal-tab / newline
; There are two kinds of comments in Leo, as in other languages.
; One is block comments of the form '/* ... */',
; and the other is end-of-line comments '// ...'.
; and the other is end-of-line comments of the form '// ...'.
; The first kind start at '/*' and end at the first '*/',
; possibly spanning multiple (partial) lines;
; they do no nest.
; these do no nest.
; The second kind start at '//' and extend till the end of the line.
; The rules about comments given below are similar to
; the ones used in the Java language specification.
; the ones used in the Java language reference.
comment = block-comment / end-of-line-comment
@ -469,9 +452,9 @@ package-name = 1*( lowercase-letter / digit )
address = %s"aleo1" 58( lowercase-letter / digit )
; A format string is a sequence of characters, other than double quote,
; A formatted string is a sequence of characters, other than double quote,
; surrounded by double quotes.
; Within a format string, substrings '{}' are distinguished as containers
; Within a formatted string, sub-strings '{}' are distinguished as containers
; (these are the ones that may be matched with values
; whose textual representation replaces the containers
; in the printed string).
@ -484,12 +467,12 @@ address = %s"aleo1" 58( lowercase-letter / digit )
formatted-string-container = "{}"
formatted-string = double-quote
*( not-double-quote / formatted-string-container )
double-quote
*( not-double-quote / formatted-string-container )
double-quote
; Here is (part of this ABNF comment),
; an alternative way to specify format strings,
; which captures the extra-grammatical requirement above in the grammar
; an alternative way to specify formatted strings,
; which captures the extra-grammatical requirement above in the grammar,
; but is more complicated:
;
; not-double-quote-or-open-brace = %x0-22 / %x24-7A / %x7C-10FFFF
@ -497,27 +480,25 @@ formatted-string = double-quote
; not-double-quote-or-close-brace = %x0-22 / %x24-7C / %x7E-10FFFF
;
; formatted-string-element = not-double-quote-or-open-brace
; / "{" not-double-quote-or-close-brace
; / formatted-string-container
; / "{" not-double-quote-or-close-brace
; / formatted-string-container
;
; formatted-string = double-quote *formatted-string-element double-quote
;
; It is not immediately clear which approach is better; there are tradeoffs.
; Regardless, we should choose one eventually.
; We may choose to adopt this one in future revisions of the grammar.
; Annotations are built out of names and arguments, which are tokens.
; Two names are currently supported.
; An argument is a sequence of one or more letters, digits, and underscores.
; Annotations have names, which are identifiers immediately preceded by '@'.
annotation-name = "@" identifier
; A natural (number) is a sequence of one or more digits.
; Note that we allow leading zeros, e.g. '007'.
; We allow leading zeros, e.g. '007'.
natural = 1*digit
; An integer (number) is either a natural or its negation.
; Note that we also allow leading zeros in negative numbers, e.g. '-007'.
; We allow leading zeros also in negative numbers, e.g. '-007'.
integer = [ "-" ] natural
@ -554,7 +535,9 @@ boolean-literal = %s"true" / %s"false"
address-literal = %s"address" "(" address ")"
; The ones above are all the literals, as defined by the following rule.
; The ones above are all the atomic literals
; (in the sense that they are tokens, without whitespace allowed in them),
; as defined by the following rule.
atomic-literal = untyped-literal
/ unsigned-literal
@ -568,14 +551,14 @@ atomic-literal = untyped-literal
; it remains to define tokens for non-alphanumeric symbols such as "+" and "(".
; Different programming languages used different terminologies for these,
; e.g. operators, separators, punctuators, etc.
; Here we use 'symbol', for all of them, but we can do something different.
; Here we use 'symbol', for all of them.
; We also include a token consisting of
; a closing parenthesis immediately followed by 'group':
; as defined in the syntactic grammar,
; this is the final part of an affine group literal.
; Even though it includes letters,
; this is the final part of an affine group literal;
; even though it includes letters,
; it seems appropriate to still consider it a symbol,
; particularly since it starts with a symbol.
; particularly since it starts with a proper symbol.
; We could give names to all of these symbols,
; via rules such as
@ -648,7 +631,7 @@ group-type = %s"group"
arithmetic-type = integer-type / field-type / group-type
; The arithmetic types, along with the boolean and address types,
; form the scalar types, i.e. the ones whose values do not contain (sub)values.
; form the scalar types, i.e. the ones whose values do not contain (sub-)values.
boolean-type = %s"bool"
@ -658,7 +641,7 @@ scalar-type = boolean-type / arithmetic-type / address-type
; Circuit types are denoted by identifiers and the keyword 'Self'.
; The latter is only allowed inside a circuit definition,
; to denote the defined circuit.
; to denote the circuit being defined.
self-type = %s"Self"
@ -670,9 +653,8 @@ tuple-type = "(" [ type 1*( "," type ) ] ")"
; An array type consists of an element type
; and an indication of dimensions.
; There is either a single dimension (a number),
; or a tuple of one or more dimensions
; (we could restrict the latter to two or more dimensions).
; There is either a single dimension,
; or a tuple of one or more dimensions.
array-type = "[" type ";" array-dimensions "]"
@ -680,7 +662,7 @@ array-dimensions = natural
/ "(" natural *( "," natural ) ")"
; Circuit, tuple, and array types form the aggregate types,
; i.e. types whose values contain (sub)values
; i.e. types whose values contain (sub-)values
; (with the corner-case exception of the empty tuple value).
aggregate-type = tuple-type / array-type / circuit-type
@ -689,23 +671,21 @@ aggregate-type = tuple-type / array-type / circuit-type
type = scalar-type / aggregate-type
; The lexical grammar above defines product group literals.
; The lexical grammar given earlier defines product group literals.
; The other kind of group literal is a pair of integer coordinates,
; which are reduced modulo the prime to identify a point,
; which must be on the elliptic curve.
; It is also allowed to omit one (not both) coordinates,
; with an indication of how to infer the missing coordinate
; It is also allowed to omit one coordinate (not both),
; with an indication of how to fill in the missing coordinate
; (i.e. sign high, sign low, or inferred).
; This is an affine group literal,
; because it consists of affine point coordinates.
group-coordinate = integer / "+" / "-" / "_"
affine-group-literal = "(" group-coordinate "," group-coordinate ")" %s"group"
affine-group-literal = "(" group-coordinate "," group-coordinate %s")group"
; A literal is either an atomic one or an affine group literal.
; Here 'atomic' refers to being a token or not,
; since no whitespace is allowed within a token.
literal = atomic-literal / affine-group-literal
@ -723,13 +703,12 @@ group-literal = product-group-literal / affine-group-literal
; and the (left or right) associativity of binary operators.
; The primary expressions are self-contained in a way,
; i.e. they have clear deliminations.
; Some consist of single tokens:
; identifiers, the keywords 'self' and 'input', and literals.
; i.e. they have clear deliminations:
; Some consist of single tokens,
; while others have explicit endings.
; Primary expressions also include parenthesized expressions,
; i.e. any expression may be turned into a primary one
; by putting parentheses around it.
; The other kinds are defined and explained below.
primary-expression = identifier
/ %s"self"
@ -739,37 +718,20 @@ primary-expression = identifier
/ tuple-expression
/ array-expression
/ circuit-expression
/ function-call
; There are tuple expressions to construct and deconstruct tuples.
; A construction consists of zero, two, or more component expressions.
; A deconstruction uses a component index (zero-indexed).
; Note that constructions are delimited by closing parentheses
; and deconstructions are delimited by natural tokens.
; The rule below, and similar rules for other aggregate types,
; use the perhaps more familiar 'access',
; but note that 'deconstruction' has a nice symmetry to 'construction';
; the term 'destructor' has a different meaning in other languages,
; so we may want to avoid it, but not necessarily.
; Tuple expressions construct tuples.
; Each consists of zero, two, or more component expressions.
tuple-construction = "(" [ expression 1*( "," expression ) ] ")"
tuple-expression = tuple-construction
; The are array expressions to construct and deconstruct arrays.
; There are two kinds of constructions:
; Array expressions construct arrays.
; There are two kinds:
; one lists the element expressions (at least one),
; including spreads (via '...') which are arrays being spliced in;
; the other repeats (the value of) a single expression
; across one or more dimensions.
; There are two kinds of deconstructions:
; one selects a single element by index (zero-indexed);
; the other selects a range via two indices,
; the first inclusive and the second exclusive --
; both are optional,
; the first defaulting to 0 and the second to the array length.
; Note that these expressions are all delimited
; by closing square brackets.
array-inline-construction = "["
array-inline-element
@ -784,17 +746,14 @@ array-construction = array-inline-construction / array-repeat-construction
array-expression = array-construction
; There are circuit expressions to construct and deconstruct circuit values.
; A construction lists values for all the member variables (in any order);
; there must be at least one member variable currently.
; Circuit expressions construct circuit values.
; Each lists values for all the member variables (in any order);
; there must be at least one member variable.
; A single identifier abbreviates
; a pair consisting of the same identifier separated by dot;
; a pair consisting of the same identifier separated by colon;
; note that, in the expansion, the left one denotes a member name,
; while the right one denotes an expression (a variable),
; so they are syntactically identical but semantically different.
; A deconstruction selects a member variable by name.
; Note that these expressions are delimited,
; by closing curly braces or identifiers.
circuit-construction = circuit-type "{"
circuit-inline-element *( "," circuit-inline-element )
@ -804,30 +763,39 @@ circuit-inline-element = identifier ":" expression / identifier
circuit-expression = circuit-construction
; After primary expressions, postfix expressions have highest precedence.
; They apply to primary expressions, and recursively to postfix expressions.
; There are postfix expressions to access parts of aggregate values.
; A tuple access selects a component by index (zero-based).
; There are two kinds of array accesses:
; one selects a single element by index (zero-based);
; the other selects a range via two indices,
; the first inclusive and the second exclusive --
; both are optional,
; the first defaulting to 0 and the second to the array length.
; A circuit access selects a member variable by name.
; Function calls are also postfix expressions.
; There are three kinds of function calls:
; top-level function calls,
; instance (i.e. non-static) member function calls, and
; static member function calls.
; What changes is the start, but they all end in an argument list,
; delimited by a closing parenthesis.
; What changes is the start, but they all end in an argument list.
function-arguments = "(" [ expression *( "," expression ) ] ")"
; Postfix expressions have highest precedence.
; They apply to primary expressions.
; Contains access expressions for arrays, tuples, and circuits.
; Contains function call types.
postfix-expression = primary-expression
/ postfix-expression "." natural
/ postfix-expression "." identifier
/ identifier function-arguments
/ postfix-expression "." identifier function-arguments
/ circuit-type "::" identifier function-arguments
/ postfix-expression "[" expression "]"
/ postfix-expression "[" [expression] ".." [expression] "]"
/ postfix-expression "." natural
/ postfix-expression "." identifier
/ identifier function-arguments
/ postfix-expression "." identifier function-arguments
/ circuit-type "::" identifier function-arguments
/ postfix-expression "[" expression "]"
/ postfix-expression "[" [expression] ".." [expression] "]"
; Unary operators have the highest operator precedence.
; They apply to postfix expressions
; They apply to postfix expressions,
; and recursively to unary expressions.
unary-expression = postfix-expression
@ -835,7 +803,7 @@ unary-expression = postfix-expression
/ "-" unary-expression
; Next in the operator precedence is casting.
; The current rule below makes exponentiation left-associative,
cast-expression = unary-expression
/ cast-expression %s"as" type
@ -843,7 +811,6 @@ cast-expression = unary-expression
; following mathematical practice.
; The current rule below makes exponentiation left-associative,
; i.e. 'a ** b ** c' must be parsed as '(a ** b) ** c'.
; This is easy to change if we want it to be right-associative instead.
exponential-expression = cast-expression
/ exponential-expression "**" cast-expression
@ -869,8 +836,8 @@ ordering-expression = additive-expression
/ additive-expression "<=" additive-expression
/ additive-expression ">=" additive-expression
; Equalities return booleans but may also operate on boolean,
; so we make them left-associative.
; Equalities return booleans but may also operate on booleans;
; the rule below makes them left-associative.
equality-expression = ordering-expression
/ equality-expression "==" ordering-expression
@ -889,11 +856,11 @@ disjunctive-expression = conjunctive-expression
; Finally we have conditional expressions.
conditional-expression = disjunctive-expression
/ conditional-expression
/ conditional-expression
"?" expression
":" conditional-expression
; These are all the expressions.
; Those above are all the expressions.
; Recall that conditional expressions
; may be disjunctive expressions,
; which may be conjunctive expressions,
@ -901,9 +868,8 @@ conditional-expression = disjunctive-expression
expression = conditional-expression
; There are various kinds of statements,
; including blocks, which are
; possibly empty sequences of statements surounded by curly braces.
; There are various kinds of statements, including blocks.
; Blocks are possibly empty sequences of statements surrounded by curly braces.
statement = expression-statement
/ return-statement
@ -916,13 +882,13 @@ statement = expression-statement
block = "{" *statement "}"
; An expression (that returns the empty tuple)
; An expression (that must return the empty tuple, as semantically required)
; can be turned into a statement by appending a semicolon.
expression-statement = expression ";"
; A return statement always takes an expression,
; and does not end with a semicolon (but we may want to change that).
; and does not end with a semicolon.
return-statement = %s"return" expression
@ -943,7 +909,7 @@ identifier-or-identifiers = identifier
; (which together form a branch).
; It may stop there, or it may continue with an alternative block,
; or possibly with another conditional statement, forming a chain.
; Note that we require blocks in all branches, not merely statements.
; Note that blocks are required in all branches, not merely statements.
branch = %s"if" expression block
@ -970,10 +936,10 @@ assignment-statement = expression assignment-operator expression ";"
; The call may be an assertion or a print command.
; The former takes an expression (which must be boolean) as argument.
; The latter takes either no argument,
; or a format string followed by expressions,
; whose number must match the number of containers '{}' in the format string.
; or a formatted string followed by expressions,
; whose number must match the number of containers '{}' in the formatted string.
; Note that the console function names are identifiers, not keywords.
; There are three kind of printing.
; There are three kinds of print commands.
console-statement = %s"console" "." console-call
@ -989,23 +955,19 @@ print-arguments = "(" [ formatted-string *( "," expression ) ] ")"
print-call = print-function print-arguments
; An annotation consists of an annotation name (which starts with '@')
; with optional annotation arguments.
; with optional annotation arguments, which are identifiers.
; Note that no parentheses are used if there are no arguments.
annotation = annotation-name
[ "(" identifier *( "," identifier ) ")" ]
; A function declaration defines a function.
; This could be called 'function-definition' instead,
; but see the comments about the 'declaration' rule below.
; The output type is optional (it defaults to the empty tuple type).
; The output type is optional, defaulting to the empty tuple type.
; In general, a function input consists of an identifier and a type,
; with an optional 'const' modifier.
; However, functions inside circuits
; may start with a 'mut self' or 'self' parameter,
; which may be the only parameter in fact.
; Furthermore, any function may end with an 'input' parameter,
; which may be the only parameter in fact.
; Additionally, functions inside circuits
; may start with a 'mut self' or 'const self' or 'self' parameter.
; Furthermore, any function may end with an 'input' parameter.
function-declaration = *annotation %s"function" identifier
"(" [ function-parameters ] ")" [ "->" type ]
@ -1016,7 +978,7 @@ function-parameters = self-parameter [ "," input-parameter ]
/ function-inputs [ "," input-parameter ]
/ input-parameter
self-parameter = [%s"mut"] %s"self"
self-parameter = [ %s"mut" / %s"const" ] %s"self"
function-inputs = function-input *( "," function-input )
@ -1026,8 +988,6 @@ input-parameter = %s"input"
; A circuit member variable declaration consists of an identifier and a type.
; A circuit member function declaration consists of a function declaration.
; We could call these 'member-definition' etc.,
; but see the comments about the 'declaration' rule below.
member-declaration = member-variable-declaration
/ member-function-declaration
@ -1036,9 +996,8 @@ member-variable-declaration = identifier ":" type
member-function-declaration = function-declaration
; A circuit declaration defines a circuit type. It is straightforward.
; This could be called 'circuit-definition' instead,
; but see the comments about the 'declaration' rule below.
; A circuit declaration defines a circuit type,
; as consisting of member variables and functions.
circuit-declaration = *annotation %s"circuit" identifier
"{" member-declaration *( "," member-declaration ) "}"
@ -1051,7 +1010,7 @@ circuit-declaration = *annotation %s"circuit" identifier
; or a parenthesized list of package paths,
; which are "fan out" of the initial path.
; Note that we allow the last element of the parenthesized list
; to be followed by a comma, presumably for convenience.
; to be followed by a comma, for convenience.
import-declaration = %s"import" package-path
@ -1061,12 +1020,6 @@ package-path = "*"
/ "(" package-path *( "," package-path ) [","] ")"
; Finally, we define a file as a sequence of zero or more declarations.
; This is why we used 'function-declaration' and 'circuit-declaration'
; instead of 'function-definition' and 'ciruit-definition':
; this way, they are all declarations of some sort.
; An import declaration cannot really called an import definition,
; because it does not define anything.
; But we may revisit this, and use 'definition' instead of 'declaration'.
declaration = import-declaration
/ function-declaration

View File

@ -198,13 +198,10 @@ fn main() -> Result<()> {
// Take Leo ABNF grammar file.
let grammar = include_str!("../abnf-grammar.txt");
// A. Coglio's proposal for %s syntax for case-sensitive statements has not been implemented
// in this library, so we need to remove all occurrences of %s in the grammar file.
// Link to this proposal: https://www.kestrel.edu/people/coglio/vstte18.pdf
let grammar = &str::replace(grammar, "%s", "");
// Parse ABNF to get list of all definitions.
let parsed = abnf::rulelist(grammar).map_err(|e| {
// Rust ABNF does not provide support for `%s` (case sensitive strings, part of
// the standard); so we need to remove all occurrences before parsing.
let parsed = abnf::rulelist(&str::replace(grammar, "%s", "")).map_err(|e| {
eprintln!("{}", &e);
anyhow::anyhow!(e)
})?;

View File

@ -45,7 +45,7 @@ impl Command for Build {
tracing::span!(tracing::Level::INFO, "Build")
}
fn prelude(&self) -> Result<Self::Input> {
fn prelude(&self, _: Context) -> Result<Self::Input> {
Ok(())
}

View File

@ -35,7 +35,7 @@ impl Command for Clean {
tracing::span!(tracing::Level::INFO, "Cleaning")
}
fn prelude(&self) -> Result<Self::Input> {
fn prelude(&self, _: Context) -> Result<Self::Input> {
Ok(())
}

View File

@ -33,7 +33,7 @@ impl Command for Deploy {
tracing::span!(tracing::Level::INFO, "Deploy")
}
fn prelude(&self) -> Result<Self::Input> {
fn prelude(&self, _: Context) -> Result<Self::Input> {
Ok(())
}

View File

@ -35,7 +35,7 @@ impl Command for Init {
tracing::span!(tracing::Level::INFO, "Initializing")
}
fn prelude(&self) -> Result<Self::Input> {
fn prelude(&self, _: Context) -> Result<Self::Input> {
Ok(())
}

View File

@ -33,7 +33,7 @@ impl Command for Lint {
tracing::span!(tracing::Level::INFO, "Linting")
}
fn prelude(&self) -> Result<Self::Input> {
fn prelude(&self, _: Context) -> Result<Self::Input> {
Ok(())
}

View File

@ -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::context::{get_context, Context};
use crate::context::Context;
use anyhow::Result;
use std::time::Instant;
@ -72,11 +72,6 @@ pub trait Command {
/// this field may be left empty.
type Output;
/// Returns the project context, which is defined as the current directory.
fn context(&self) -> Result<Context> {
get_context()
}
/// Adds a span to the logger via `tracing::span`.
/// Because of the specifics of the macro implementation, it is not possible
/// to set the span name with a non-literal i.e. a dynamic variable even if this
@ -86,7 +81,7 @@ pub trait Command {
}
/// Runs the prelude and returns the Input of the current command.
fn prelude(&self) -> Result<Self::Input>
fn prelude(&self, context: Context) -> Result<Self::Input>
where
Self: std::marker::Sized;
@ -98,11 +93,11 @@ pub trait Command {
/// A wrapper around the `apply` method.
/// This function sets up tracing, timing, and the context.
fn execute(self) -> Result<Self::Output>
fn execute(self, context: Context) -> Result<Self::Output>
where
Self: std::marker::Sized,
{
let input = self.prelude()?;
let input = self.prelude(context.clone())?;
// Create the span for this command.
let span = self.log_span();
@ -110,8 +105,6 @@ pub trait Command {
// Calculate the execution time for this command.
let timer = Instant::now();
let context = self.context()?;
let out = self.apply(context, input);
drop(span);
@ -127,10 +120,10 @@ pub trait Command {
/// Executes command but empty the result. Comes in handy where there's a
/// need to make match arms compatible while keeping implementation-specific
/// output possible. Errors however are all of the type Error
fn try_execute(self) -> Result<()>
fn try_execute(self, context: Context) -> Result<()>
where
Self: std::marker::Sized,
{
self.execute().map(|_| Ok(()))?
self.execute(context).map(|_| Ok(()))?
}
}

View File

@ -38,7 +38,7 @@ impl Command for New {
tracing::span!(tracing::Level::INFO, "New")
}
fn prelude(&self) -> Result<Self::Input> {
fn prelude(&self, _: Context) -> Result<Self::Input> {
Ok(())
}

View File

@ -86,7 +86,7 @@ impl Command for Add {
tracing::span!(tracing::Level::INFO, "Adding")
}
fn prelude(&self) -> Result<Self::Input> {
fn prelude(&self, _: Context) -> Result<Self::Input> {
Ok(())
}

View File

@ -103,7 +103,7 @@ impl Command for Clone {
tracing::span!(tracing::Level::INFO, "Cloning")
}
fn prelude(&self) -> Result<Self::Input> {
fn prelude(&self, _: Context) -> Result<Self::Input> {
Ok(())
}

View File

@ -54,7 +54,7 @@ impl Command for Login {
tracing::span!(tracing::Level::INFO, "Login")
}
fn prelude(&self) -> Result<Self::Input> {
fn prelude(&self, _: Context) -> Result<Self::Input> {
Ok(())
}

View File

@ -34,7 +34,7 @@ impl Command for Logout {
tracing::span!(tracing::Level::INFO, "Logout")
}
fn prelude(&self) -> Result<Self::Input> {
fn prelude(&self, _: Context) -> Result<Self::Input> {
Ok(())
}

View File

@ -46,8 +46,8 @@ impl Command for Publish {
type Output = Option<String>;
/// Build program before publishing
fn prelude(&self) -> Result<Self::Input> {
(Build {}).execute()
fn prelude(&self, context: Context) -> Result<Self::Input> {
(Build {}).execute(context)
}
fn apply(self, context: Context, _input: Self::Input) -> Result<Self::Output> {

View File

@ -37,7 +37,7 @@ impl Command for Remove {
tracing::span!(tracing::Level::INFO, "Removing")
}
fn prelude(&self) -> Result<Self::Input> {
fn prelude(&self, _: Context) -> Result<Self::Input> {
Ok(())
}

View File

@ -45,9 +45,9 @@ impl Command for Prove {
tracing::span!(tracing::Level::INFO, "Proving")
}
fn prelude(&self) -> Result<Self::Input> {
fn prelude(&self, context: Context) -> Result<Self::Input> {
let skip_key_check = self.skip_key_check;
(Setup { skip_key_check }).execute()
(Setup { skip_key_check }).execute(context)
}
fn apply(self, context: Context, input: Self::Input) -> Result<Self::Output> {

View File

@ -40,9 +40,9 @@ impl Command for Run {
tracing::span!(tracing::Level::INFO, "Verifying")
}
fn prelude(&self) -> Result<Self::Input> {
fn prelude(&self, context: Context) -> Result<Self::Input> {
let skip_key_check = self.skip_key_check;
(Prove { skip_key_check }).execute()
(Prove { skip_key_check }).execute(context)
}
fn apply(self, _context: Context, input: Self::Input) -> Result<Self::Output> {

View File

@ -49,8 +49,8 @@ impl Command for Setup {
tracing::span!(tracing::Level::INFO, "Setup")
}
fn prelude(&self) -> Result<Self::Input> {
(Build {}).execute()
fn prelude(&self, context: Context) -> Result<Self::Input> {
(Build {}).execute(context)
}
fn apply(self, context: Context, input: Self::Input) -> Result<Self::Output> {

View File

@ -47,7 +47,7 @@ impl Command for Test {
tracing::span!(tracing::Level::INFO, "Test")
}
fn prelude(&self) -> Result<Self::Input> {
fn prelude(&self, _: Context) -> Result<Self::Input> {
Ok(())
}

View File

@ -54,7 +54,7 @@ impl Command for Update {
tracing::span!(tracing::Level::INFO, "Updating")
}
fn prelude(&self) -> Result<Self::Input> {
fn prelude(&self, _: Context) -> Result<Self::Input> {
Ok(())
}

View File

@ -43,11 +43,11 @@ impl Command for Watch {
tracing::span!(tracing::Level::INFO, "Watching")
}
fn prelude(&self) -> Result<Self::Input> {
fn prelude(&self, _: Context) -> Result<Self::Input> {
Ok(())
}
fn apply(self, _context: Context, _: Self::Input) -> Result<Self::Output> {
fn apply(self, context: Context, _: Self::Input) -> Result<Self::Output> {
let (tx, rx) = channel();
let mut watcher = watcher(tx, Duration::from_secs(self.interval)).unwrap();
@ -64,7 +64,7 @@ impl Command for Watch {
match rx.recv() {
// See changes on the write event
Ok(DebouncedEvent::Write(_write)) => {
match (Build {}).execute() {
match (Build {}).execute(context.clone()) {
Ok(_output) => {
tracing::info!("Built successfully");
}

View File

@ -39,21 +39,29 @@ use commands::{
};
use anyhow::Error;
use std::process::exit;
use std::{path::PathBuf, process::exit};
use structopt::{clap::AppSettings, StructOpt};
/// CLI Arguments entry point - includes global parameters and subcommands
#[derive(StructOpt, Debug)]
#[structopt(name = "leo", author = "The Aleo Team <hello@aleo.org>", setting = AppSettings::ColoredHelp)]
struct Opt {
#[structopt(short, long, help = "Print additional information for debugging")]
#[structopt(short, global = true, help = "Print additional information for debugging")]
debug: bool,
#[structopt(short, long, help = "Suppress CLI output")]
#[structopt(short, global = true, help = "Suppress CLI output")]
quiet: bool,
#[structopt(subcommand)]
command: CommandOpts,
#[structopt(
long,
global = true,
help = "Optional path to Leo program root folder",
parse(from_os_str)
)]
path: Option<PathBuf>,
}
///Leo compiler and package manager
@ -170,38 +178,45 @@ enum CommandOpts {
}
fn main() {
// read command line arguments
// Read command line arguments.
let opt = Opt::from_args();
if !opt.quiet {
// init logger with optional debug flag
// Init logger with optional debug flag.
logger::init_logger("leo", match opt.debug {
false => 1,
true => 2,
});
}
// Get custom root folder and create context for it.
// If not specified, default context will be created in cwd.
let context = handle_error(match opt.path {
Some(path) => context::create_context(path),
None => context::get_context(),
});
handle_error(match opt.command {
CommandOpts::Init { command } => command.try_execute(),
CommandOpts::New { command } => command.try_execute(),
CommandOpts::Build { command } => command.try_execute(),
CommandOpts::Setup { command } => command.try_execute(),
CommandOpts::Prove { command } => command.try_execute(),
CommandOpts::Test { command } => command.try_execute(),
CommandOpts::Run { command } => command.try_execute(),
CommandOpts::Clean { command } => command.try_execute(),
CommandOpts::Watch { command } => command.try_execute(),
CommandOpts::Update { command } => command.try_execute(),
CommandOpts::Init { command } => command.try_execute(context),
CommandOpts::New { command } => command.try_execute(context),
CommandOpts::Build { command } => command.try_execute(context),
CommandOpts::Setup { command } => command.try_execute(context),
CommandOpts::Prove { command } => command.try_execute(context),
CommandOpts::Test { command } => command.try_execute(context),
CommandOpts::Run { command } => command.try_execute(context),
CommandOpts::Clean { command } => command.try_execute(context),
CommandOpts::Watch { command } => command.try_execute(context),
CommandOpts::Update { command } => command.try_execute(context),
CommandOpts::Add { command } => command.try_execute(),
CommandOpts::Clone { command } => command.try_execute(),
CommandOpts::Login { command } => command.try_execute(),
CommandOpts::Logout { command } => command.try_execute(),
CommandOpts::Publish { command } => command.try_execute(),
CommandOpts::Remove { command } => command.try_execute(),
CommandOpts::Add { command } => command.try_execute(context),
CommandOpts::Clone { command } => command.try_execute(context),
CommandOpts::Login { command } => command.try_execute(context),
CommandOpts::Logout { command } => command.try_execute(context),
CommandOpts::Publish { command } => command.try_execute(context),
CommandOpts::Remove { command } => command.try_execute(context),
CommandOpts::Lint { command } => command.try_execute(),
CommandOpts::Deploy { command } => command.try_execute(),
CommandOpts::Lint { command } => command.try_execute(context),
CommandOpts::Deploy { command } => command.try_execute(context),
});
}

View File

@ -68,10 +68,16 @@ impl Package {
return false;
}
// Check that the first character is not a number.
if previous.is_numeric() {
tracing::error!("Project names cannot begin with a number");
return false;
}
// Iterate and check that the package name is valid.
for current in package_name.chars() {
// Check that the package name is lowercase.
if !current.is_ascii_lowercase() && current != '-' {
if current.is_ascii_uppercase() && current != '-' {
tracing::error!("Project names must be all lowercase");
return false;
}
@ -267,6 +273,8 @@ mod tests {
assert!(Package::is_package_name_valid("foo"));
assert!(Package::is_package_name_valid("foo-bar"));
assert!(Package::is_package_name_valid("foo-bar-baz"));
assert!(Package::is_package_name_valid("foo1"));
assert!(Package::is_package_name_valid("foo-1"));
assert!(!Package::is_package_name_valid(""));
assert!(!Package::is_package_name_valid("-"));
@ -279,5 +287,6 @@ mod tests {
assert!(!Package::is_package_name_valid("foo*bar"));
assert!(!Package::is_package_name_valid("foo,bar"));
assert!(!Package::is_package_name_valid("foo_bar"));
assert!(!Package::is_package_name_valid("1-foo"));
}
}

View File

@ -26,19 +26,19 @@ path = "../ast"
version = "1.2.3"
[dependencies.snarkvm-algorithms]
version = "0.2.1"
version = "0.2.2"
#default-features = false
[dependencies.snarkvm-curves]
version = "0.2.1"
version = "0.2.2"
default-features = false
[dependencies.snarkvm-dpc]
version = "0.2.1"
version = "0.2.2"
default-features = false
[dependencies.snarkvm-utilities]
version = "0.2.1"
version = "0.2.2"
[dependencies.indexmap]
version = "1.6.2"
@ -54,7 +54,7 @@ version = "0.3"
version = "1.0"
[dev-dependencies.snarkvm-storage]
version = "0.2.1"
version = "0.2.2"
[dev-dependencies.rand_core]
version = "0.6.2"

View File

@ -18,19 +18,19 @@ license = "GPL-3.0"
edition = "2018"
[dependencies.snarkvm-curves]
version = "0.2.1"
version = "0.2.2"
default-features = false
[dependencies.snarkvm-fields]
version = "0.2.1"
version = "0.2.2"
default-features = false
[dependencies.snarkvm-gadgets]
version = "0.2.1"
version = "0.2.2"
default-features = false
[dependencies.snarkvm-r1cs]
version = "0.2.1"
version = "0.2.2"
default-features = false
[dependencies.num-bigint]