diff --git a/.resources/release-version b/.resources/release-version index 74a63a2249..01558e339a 100644 --- a/.resources/release-version +++ b/.resources/release-version @@ -1 +1 @@ -v1.5.2 \ No newline at end of file +v1.5.3 \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 27eab99cb2..d18dc2919a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1159,7 +1159,7 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "leo-abnf" -version = "1.5.2" +version = "1.5.3" dependencies = [ "abnf", "anyhow", @@ -1167,7 +1167,7 @@ dependencies = [ [[package]] name = "leo-asg" -version = "1.5.2" +version = "1.5.3" dependencies = [ "criterion", "indexmap", @@ -1183,14 +1183,14 @@ dependencies = [ [[package]] name = "leo-asg-passes" -version = "1.5.2" +version = "1.5.3" dependencies = [ "leo-asg", ] [[package]] name = "leo-ast" -version = "1.5.2" +version = "1.5.3" dependencies = [ "anyhow", "criterion", @@ -1205,7 +1205,7 @@ dependencies = [ [[package]] name = "leo-compiler" -version = "1.5.2" +version = "1.5.3" dependencies = [ "bincode", "hex", @@ -1243,7 +1243,7 @@ dependencies = [ [[package]] name = "leo-imports" -version = "1.5.2" +version = "1.5.3" dependencies = [ "indexmap", "leo-asg", @@ -1255,7 +1255,7 @@ dependencies = [ [[package]] name = "leo-input" -version = "1.5.2" +version = "1.5.3" dependencies = [ "from-pest", "pest", @@ -1267,7 +1267,7 @@ dependencies = [ [[package]] name = "leo-lang" -version = "1.5.2" +version = "1.5.3" dependencies = [ "ansi_term 0.12.1", "anyhow", @@ -1311,11 +1311,11 @@ dependencies = [ [[package]] name = "leo-linter" -version = "1.5.2" +version = "1.5.3" [[package]] name = "leo-package" -version = "1.5.2" +version = "1.5.3" dependencies = [ "indexmap", "lazy_static", @@ -1329,7 +1329,7 @@ dependencies = [ [[package]] name = "leo-parser" -version = "1.5.2" +version = "1.5.3" dependencies = [ "criterion", "indexmap", @@ -1346,7 +1346,7 @@ dependencies = [ [[package]] name = "leo-state" -version = "1.5.2" +version = "1.5.3" dependencies = [ "indexmap", "leo-ast", @@ -1363,7 +1363,7 @@ dependencies = [ [[package]] name = "leo-synthesizer" -version = "1.5.2" +version = "1.5.3" dependencies = [ "hex", "num-bigint", @@ -1378,7 +1378,7 @@ dependencies = [ [[package]] name = "leo-test-framework" -version = "1.5.2" +version = "1.5.3" dependencies = [ "serde", "serde_json", diff --git a/Cargo.toml b/Cargo.toml index 4667219476..acdb0c7ea3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "leo-lang" -version = "1.5.2" +version = "1.5.3" authors = [ "The Aleo Team " ] description = "The Leo programming language" homepage = "https://aleo.org" @@ -43,35 +43,35 @@ members = [ [dependencies.leo-ast] path = "./ast" -version = "1.5.2" +version = "1.5.3" [dependencies.leo-compiler] path = "./compiler" -version = "1.5.2" +version = "1.5.3" [dependencies.leo-imports] path = "./imports" -version = "1.5.2" +version = "1.5.3" [dependencies.leo-input] path = "./input" -version = "1.5.2" +version = "1.5.3" [dependencies.leo-package] path = "./package" -version = "1.5.2" +version = "1.5.3" [dependencies.leo-parser] path = "./parser" -version = "1.5.2" +version = "1.5.3" [dependencies.leo-state] path = "./state" -version = "1.5.2" +version = "1.5.3" [dependencies.leo-synthesizer] path = "./synthesizer" -version = "1.5.2" +version = "1.5.3" [dependencies.snarkvm-algorithms] version = "0.7.4" diff --git a/asg-passes/Cargo.toml b/asg-passes/Cargo.toml index 83b0a0a066..6b5ca6d4f6 100644 --- a/asg-passes/Cargo.toml +++ b/asg-passes/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "leo-asg-passes" -version = "1.5.2" +version = "1.5.3" authors = [ "The Aleo Team " ] description = "The Leo programming language" homepage = "https://aleo.org" @@ -22,4 +22,4 @@ path = "src/lib.rs" [dependencies.leo-asg] path = "../asg" -version = "1.5.2" +version = "1.5.3" diff --git a/asg/Cargo.toml b/asg/Cargo.toml index cd95da9596..f41ef3b108 100644 --- a/asg/Cargo.toml +++ b/asg/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "leo-asg" -version = "1.5.2" +version = "1.5.3" authors = [ "The Aleo Team " ] description = "ASG of the Leo programming language" homepage = "https://aleo.org" @@ -30,11 +30,11 @@ version = "1.7" version = "1.0" [dependencies.leo-ast] -version = "1.5.2" +version = "1.5.3" path = "../ast" [dependencies.leo-parser] -version = "1.5.2" +version = "1.5.3" path = "../parser" [dependencies.num-bigint] diff --git a/asg/src/reducer/monoidal_director.rs b/asg/src/reducer/monoidal_director.rs index ce34755a11..161183a19b 100644 --- a/asg/src/reducer/monoidal_director.rs +++ b/asg/src/reducer/monoidal_director.rs @@ -238,9 +238,7 @@ impl<'a, T: Monoid, R: MonoidalReducerStatement<'a, T>> MonoidalDirector<'a, T, pub fn reduce_console(&mut self, input: &ConsoleStatement<'a>) -> T { let argument = match &input.function { ConsoleFunction::Assert(e) => self.reduce_expression(e.get()), - ConsoleFunction::Debug(f) | ConsoleFunction::Error(f) | ConsoleFunction::Log(f) => { - self.reduce_formatted_string(f) - } + ConsoleFunction::Error(f) | ConsoleFunction::Log(f) => self.reduce_formatted_string(f), }; self.reducer.reduce_console(input, argument) diff --git a/asg/src/reducer/reconstructing_director.rs b/asg/src/reducer/reconstructing_director.rs index 75127d477a..bd2900d3e8 100644 --- a/asg/src/reducer/reconstructing_director.rs +++ b/asg/src/reducer/reconstructing_director.rs @@ -259,7 +259,7 @@ impl<'a, R: ReconstructingReducerStatement<'a>> ReconstructingDirector<'a, R> { let argument = self.reduce_expression(argument.get()); self.reducer.reduce_console_assert(input, argument) } - ConsoleFunction::Debug(f) | ConsoleFunction::Error(f) | ConsoleFunction::Log(f) => { + ConsoleFunction::Error(f) | ConsoleFunction::Log(f) => { let formatted = self.reduce_formatted_string(f.clone()); self.reducer.reduce_console_log(input, formatted) } diff --git a/asg/src/reducer/reconstructing_reducer.rs b/asg/src/reducer/reconstructing_reducer.rs index 755c2eed1c..1a17b886c0 100644 --- a/asg/src/reducer/reconstructing_reducer.rs +++ b/asg/src/reducer/reconstructing_reducer.rs @@ -300,7 +300,6 @@ pub trait ReconstructingReducerStatement<'a>: ReconstructingReducerExpression<'a span: input.span, function: match input.function { ConsoleFunction::Assert(_) => unimplemented!(), - ConsoleFunction::Debug(_) => ConsoleFunction::Debug(argument), ConsoleFunction::Error(_) => ConsoleFunction::Error(argument), ConsoleFunction::Log(_) => ConsoleFunction::Log(argument), }, diff --git a/asg/src/reducer/visitor_director.rs b/asg/src/reducer/visitor_director.rs index dc6dae6929..2d238e67aa 100644 --- a/asg/src/reducer/visitor_director.rs +++ b/asg/src/reducer/visitor_director.rs @@ -336,9 +336,7 @@ impl<'a, R: StatementVisitor<'a>> VisitorDirector<'a, R> { VisitResult::VisitChildren => { match &input.function { ConsoleFunction::Assert(e) => self.visit_expression(e)?, - ConsoleFunction::Debug(f) | ConsoleFunction::Error(f) | ConsoleFunction::Log(f) => { - self.visit_formatted_string(f)? - } + ConsoleFunction::Error(f) | ConsoleFunction::Log(f) => self.visit_formatted_string(f)?, } Ok(()) } diff --git a/asg/src/statement/console.rs b/asg/src/statement/console.rs index 37359f90b3..5708576425 100644 --- a/asg/src/statement/console.rs +++ b/asg/src/statement/console.rs @@ -30,7 +30,6 @@ pub struct ConsoleArgs<'a> { #[derive(Clone)] pub enum ConsoleFunction<'a> { Assert(Cell<&'a Expression<'a>>), - Debug(ConsoleArgs<'a>), Error(ConsoleArgs<'a>), Log(ConsoleArgs<'a>), } @@ -89,7 +88,6 @@ impl<'a> FromAst<'a, leo_ast::ConsoleStatement> for ConsoleStatement<'a> { AstConsoleFunction::Assert(expression) => ConsoleFunction::Assert(Cell::new( <&Expression<'a>>::from_ast(scope, expression, Some(Type::Boolean.into()))?, )), - AstConsoleFunction::Debug(args) => ConsoleFunction::Debug(ConsoleArgs::from_ast(scope, args, None)?), AstConsoleFunction::Error(args) => ConsoleFunction::Error(ConsoleArgs::from_ast(scope, args, None)?), AstConsoleFunction::Log(args) => ConsoleFunction::Log(ConsoleArgs::from_ast(scope, args, None)?), }, @@ -103,7 +101,6 @@ impl<'a> Into for &ConsoleStatement<'a> { leo_ast::ConsoleStatement { function: match &self.function { Assert(e) => AstConsoleFunction::Assert(e.get().into()), - Debug(args) => AstConsoleFunction::Debug(args.into()), Error(args) => AstConsoleFunction::Error(args.into()), Log(args) => AstConsoleFunction::Log(args.into()), }, diff --git a/asg/tests/pass/console/debug.leo b/asg/tests/pass/console/debug.leo deleted file mode 100644 index 54e6eb539f..0000000000 --- a/asg/tests/pass/console/debug.leo +++ /dev/null @@ -1,3 +0,0 @@ -function main() { - console.debug("hello debug"); -} \ No newline at end of file diff --git a/asg/tests/pass/console/mod.rs b/asg/tests/pass/console/mod.rs index 4f1a243012..43d3c0e0cb 100644 --- a/asg/tests/pass/console/mod.rs +++ b/asg/tests/pass/console/mod.rs @@ -40,14 +40,6 @@ fn test_log_input() { load_asg(program_string).unwrap(); } -// Debug - -#[test] -fn test_debug() { - let program_string = include_str!("debug.leo"); - load_asg(program_string).unwrap(); -} - // Error #[test] diff --git a/ast/Cargo.toml b/ast/Cargo.toml index 43092b85f3..c33cd7f912 100644 --- a/ast/Cargo.toml +++ b/ast/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "leo-ast" -version = "1.5.2" +version = "1.5.3" authors = [ "The Aleo Team " ] description = "Core AST of the Leo programming language" homepage = "https://aleo.org" @@ -19,7 +19,7 @@ edition = "2018" [dependencies.leo-input] path = "../input" -version = "1.5.2" +version = "1.5.3" [dependencies.indexmap] version = "1.7.0" diff --git a/ast/src/errors/error.rs b/ast/src/errors/error.rs index 0cf34f5d25..b2c1ebff5a 100644 --- a/ast/src/errors/error.rs +++ b/ast/src/errors/error.rs @@ -15,7 +15,6 @@ // along with the Leo library. If not, see . use crate::{LeoError, Span}; - use std::{fmt, sync::Arc}; pub const INDENT: &str = " "; @@ -77,20 +76,21 @@ impl fmt::Display for FormattedError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let underline = underline(self.col_start, self.col_stop); - write!( - f, + let error_message = format!( "{indent }--> {path}:{line_start}:{start}\n\ - {indent } |\n", + {indent } ", indent = INDENT, path = &*self.path, line_start = self.line_start, start = self.col_start, - )?; + ); + + write!(f, "{}", error_message)?; for (line_no, line) in self.content.lines().enumerate() { writeln!( f, - "{line_no:width$} | {text}", + "|\n{line_no:width$} | {text}", width = INDENT.len(), line_no = self.line_start + line_no, text = line, diff --git a/ast/src/reducer/canonicalization.rs b/ast/src/reducer/canonicalization.rs index 4c78012c30..edf300ada4 100644 --- a/ast/src/reducer/canonicalization.rs +++ b/ast/src/reducer/canonicalization.rs @@ -392,7 +392,7 @@ impl Canonicalizer { ConsoleFunction::Assert(expression) => { ConsoleFunction::Assert(self.canonicalize_expression(expression)) } - ConsoleFunction::Debug(args) | ConsoleFunction::Error(args) | ConsoleFunction::Log(args) => { + ConsoleFunction::Error(args) | ConsoleFunction::Log(args) => { let parameters = args .parameters .iter() @@ -406,7 +406,6 @@ impl Canonicalizer { }; match &console_function_call.function { - ConsoleFunction::Debug(_) => ConsoleFunction::Debug(console_args), ConsoleFunction::Error(_) => ConsoleFunction::Error(console_args), ConsoleFunction::Log(_) => ConsoleFunction::Log(console_args), _ => unimplemented!(), // impossible diff --git a/ast/src/reducer/reconstructing_director.rs b/ast/src/reducer/reconstructing_director.rs index 80a61e0476..cf5a409d06 100644 --- a/ast/src/reducer/reconstructing_director.rs +++ b/ast/src/reducer/reconstructing_director.rs @@ -390,7 +390,7 @@ impl ReconstructingDirector { ) -> Result { let function = match &console_function_call.function { ConsoleFunction::Assert(expression) => ConsoleFunction::Assert(self.reduce_expression(expression)?), - ConsoleFunction::Debug(args) | ConsoleFunction::Error(args) | ConsoleFunction::Log(args) => { + ConsoleFunction::Error(args) | ConsoleFunction::Log(args) => { let mut parameters = vec![]; for parameter in args.parameters.iter() { parameters.push(self.reduce_expression(parameter)?); @@ -403,7 +403,6 @@ impl ReconstructingDirector { }; match &console_function_call.function { - ConsoleFunction::Debug(_) => ConsoleFunction::Debug(formatted), ConsoleFunction::Error(_) => ConsoleFunction::Error(formatted), ConsoleFunction::Log(_) => ConsoleFunction::Log(formatted), _ => return Err(ReducerError::impossible_console_assert_call(&args.span)), diff --git a/ast/src/statements/console/console_function.rs b/ast/src/statements/console/console_function.rs index 5919980af6..8c782a1e88 100644 --- a/ast/src/statements/console/console_function.rs +++ b/ast/src/statements/console/console_function.rs @@ -22,7 +22,6 @@ use std::fmt; #[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] pub enum ConsoleFunction { Assert(Expression), - Debug(ConsoleArgs), Error(ConsoleArgs), Log(ConsoleArgs), } @@ -31,7 +30,6 @@ impl fmt::Display for ConsoleFunction { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { ConsoleFunction::Assert(assert) => write!(f, "assert({})", assert), - ConsoleFunction::Debug(debug) => write!(f, "debug({})", debug), ConsoleFunction::Error(error) => write!(f, "error{})", error), ConsoleFunction::Log(log) => write!(f, "log({})", log), } @@ -42,18 +40,14 @@ impl Node for ConsoleFunction { fn span(&self) -> &Span { match self { ConsoleFunction::Assert(assert) => assert.span(), - ConsoleFunction::Debug(formatted) | ConsoleFunction::Error(formatted) | ConsoleFunction::Log(formatted) => { - &formatted.span - } + ConsoleFunction::Error(formatted) | ConsoleFunction::Log(formatted) => &formatted.span, } } fn set_span(&mut self, span: Span) { match self { ConsoleFunction::Assert(assert) => assert.set_span(span), - ConsoleFunction::Debug(formatted) | ConsoleFunction::Error(formatted) | ConsoleFunction::Log(formatted) => { - formatted.set_span(span) - } + ConsoleFunction::Error(formatted) | ConsoleFunction::Log(formatted) => formatted.set_span(span), } } } diff --git a/compiler/Cargo.toml b/compiler/Cargo.toml index 07c7508152..5725a5f453 100644 --- a/compiler/Cargo.toml +++ b/compiler/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "leo-compiler" -version = "1.5.2" +version = "1.5.3" authors = [ "The Aleo Team " ] description = "Compiler of the Leo programming language" homepage = "https://aleo.org" @@ -19,39 +19,39 @@ edition = "2018" [dependencies.leo-ast] path = "../ast" -version = "1.5.2" +version = "1.5.3" [dependencies.leo-imports] path = "../imports" -version = "1.5.2" +version = "1.5.3" [dependencies.leo-input] path = "../input" -version = "1.5.2" +version = "1.5.3" [dependencies.leo-package] path = "../package" -version = "1.5.2" +version = "1.5.3" [dependencies.leo-state] path = "../state" -version = "1.5.2" +version = "1.5.3" [dependencies.leo-asg] path = "../asg" -version = "1.5.2" +version = "1.5.3" [dependencies.leo-parser] path = "../parser" -version = "1.5.2" +version = "1.5.3" [dependencies.leo-asg-passes] path = "../asg-passes" -version = "1.5.2" +version = "1.5.3" [dependencies.leo-synthesizer] path = "../synthesizer" -version = "1.5.2" +version = "1.5.3" [dependencies.tendril] version = "0.4" @@ -71,7 +71,7 @@ default-features = false [dependencies.snarkvm-gadgets] version = "0.7.5" default-features = false -features = ["curves"] +features = [ "curves" ] [dependencies.snarkvm-r1cs] version = "0.7.5" diff --git a/compiler/src/console/console.rs b/compiler/src/console/console.rs index e3aa490942..46f3dee52a 100644 --- a/compiler/src/console/console.rs +++ b/compiler/src/console/console.rs @@ -39,13 +39,6 @@ impl<'a, F: PrimeField, G: GroupType> ConstrainedProgram<'a, F, G> { &console.span.clone().unwrap_or_default(), )?; } - ConsoleFunction::Debug(string) => { - let string = self.format(cs, string)?; - - if get_indicator_value(indicator) { - tracing::debug!("{}", string); - } - } ConsoleFunction::Error(string) => { let string = self.format(cs, string)?; diff --git a/compiler/src/phases/reducing_director.rs b/compiler/src/phases/reducing_director.rs index ff432e3f27..2a934909a8 100644 --- a/compiler/src/phases/reducing_director.rs +++ b/compiler/src/phases/reducing_director.rs @@ -597,8 +597,7 @@ impl CombineAstAsgDirector { (AstConsoleFunction::Assert(ast_expression), AsgConsoleFunction::Assert(asg_expression)) => { AstConsoleFunction::Assert(self.reduce_expression(&ast_expression, asg_expression.get())?) } - (AstConsoleFunction::Debug(ast_console_args), AsgConsoleFunction::Debug(asg_format)) - | (AstConsoleFunction::Error(ast_console_args), AsgConsoleFunction::Error(asg_format)) + (AstConsoleFunction::Error(ast_console_args), AsgConsoleFunction::Error(asg_format)) | (AstConsoleFunction::Log(ast_console_args), AsgConsoleFunction::Log(asg_format)) => { let mut parameters = vec![]; for (ast_parameter, asg_parameter) in @@ -614,7 +613,6 @@ impl CombineAstAsgDirector { }; match &ast.function { - AstConsoleFunction::Debug(_) => AstConsoleFunction::Debug(args), AstConsoleFunction::Error(_) => AstConsoleFunction::Error(args), AstConsoleFunction::Log(_) => AstConsoleFunction::Log(args), _ => return Err(ReducerError::impossible_console_assert_call(&ast_console_args.span)), diff --git a/compiler/src/test.rs b/compiler/src/test.rs index c690cfb051..c1cf0d5bc9 100644 --- a/compiler/src/test.rs +++ b/compiler/src/test.rs @@ -235,7 +235,9 @@ impl Namespace for CompileNamespace { .unwrap_or_else(|_| "Error converting ast to string.".to_string()), ); - std::fs::remove_dir_all(std::path::Path::new("/tmp/output")).expect("Error failed to clean up output dir."); + if std::fs::read_dir("/tmp/output").is_ok() { + std::fs::remove_dir_all(std::path::Path::new("/tmp/output")).expect("Error failed to clean up output dir."); + } let final_output = CompileOutput { circuit: last_circuit.unwrap(), diff --git a/compiler/src/value/address/address.rs b/compiler/src/value/address/address.rs index f706448c4d..a9fd35a42a 100644 --- a/compiler/src/value/address/address.rs +++ b/compiler/src/value/address/address.rs @@ -85,33 +85,57 @@ impl Address { Ok(ConstrainedValue::Address(address)) } - pub(crate) fn alloc_helper Result, T: Borrow>( + pub(crate) fn alloc_helper< + F: PrimeField, + CS: ConstraintSystem, + Fn: FnOnce() -> Result, + T: Borrow, + >( + cs: CS, value_gen: Fn, ) -> Result, SynthesisError> { - let address_string = match value_gen() { - Ok(value) => { - let string_value = value.borrow().clone(); - Ok(string_value) - } - _ => Err(SynthesisError::AssignmentMissing), - }?; - - AleoAddress::from_str(&address_string).map_err(|_| SynthesisError::AssignmentMissing) + if cs.is_in_setup_mode() { + Ok(AleoAddress::::default()) + } else { + let address_string = value_gen()?.borrow().clone(); + AleoAddress::from_str(&address_string).map_err(|_| SynthesisError::AssignmentMissing) + } } } impl AllocGadget for Address { - fn alloc Result, T: Borrow, CS: ConstraintSystem>( - cs: CS, + fn alloc_constant Result, T: Borrow, CS: ConstraintSystem>( + _cs: CS, value_gen: Fn, ) -> Result { - let address = Self::alloc_helper(value_gen)?; + let address = { + let address_string = value_gen()?.borrow().clone(); + AleoAddress::from_str(&address_string).map_err(|_| SynthesisError::AssignmentMissing)? + }; let mut address_bytes = vec![]; address .write_le(&mut address_bytes) .map_err(|_| SynthesisError::AssignmentMissing)?; - let bytes = UInt8::alloc_vec(cs, &address_bytes[..])?; + let bytes = UInt8::constant_vec(&address_bytes[..]); + + Ok(Address { + address: Some(address), + bytes, + }) + } + + fn alloc Result, T: Borrow, CS: ConstraintSystem>( + mut cs: CS, + value_gen: Fn, + ) -> Result { + let address = Self::alloc_helper(cs.ns(|| "allocate the address"), value_gen)?; + let mut address_bytes = vec![]; + address + .write_le(&mut address_bytes) + .map_err(|_| SynthesisError::AssignmentMissing)?; + + let bytes = UInt8::alloc_vec(cs.ns(|| "allocate the address bytes"), &address_bytes[..])?; Ok(Address { address: Some(address), @@ -120,16 +144,16 @@ impl AllocGadget for Address { } fn alloc_input Result, T: Borrow, CS: ConstraintSystem>( - cs: CS, + mut cs: CS, value_gen: Fn, ) -> Result { - let address = Self::alloc_helper(value_gen)?; + let address = Self::alloc_helper(cs.ns(|| "allocate the address"), value_gen)?; let mut address_bytes = vec![]; address .write_le(&mut address_bytes) .map_err(|_| SynthesisError::AssignmentMissing)?; - let bytes = UInt8::alloc_input_vec_le(cs, &address_bytes[..])?; + let bytes = UInt8::alloc_input_vec_le(cs.ns(|| "allocate the address bytes"), &address_bytes[..])?; Ok(Address { address: Some(address), diff --git a/docs/rfc/006-arrays-without-size.md b/docs/rfc/006-arrays-without-size.md index 51e0e08f71..0fc67ac6c6 100644 --- a/docs/rfc/006-arrays-without-size.md +++ b/docs/rfc/006-arrays-without-size.md @@ -120,6 +120,15 @@ Thus, this RFC also proposed to extend Leo with such an operator. A possibility is `.length`, where `` is an expression of array type. A variation is `.length()`, if we want it look more like a built-in method on arrays. Yet another option is `length()`, which is more like a built-in function. +A shorter name could be `len`, leading to the three possibilities +`.len`, `.len()`, and `len()`. +So one dimension of the choice is the name (`length` vs. `len`), +and another dimension is the style: +member variable style, +member function style, +or global function style. +The decision on the latter should be driven by broader considerations +of how we want to treat this kind of built-in operators. Note that the result of this operator can, and in fact must, be calculated at compile time; not as part of the Leo interpreter, but rather as part of the flattening of Leo to R1CS. diff --git a/docs/rfc/007-type-aliases.md b/docs/rfc/007-type-aliases.md new file mode 100644 index 0000000000..4929e56a72 --- /dev/null +++ b/docs/rfc/007-type-aliases.md @@ -0,0 +1,162 @@ +# Leo RFC 007: Type Aliases + +## Authors + +- Max Bruce +- Collin Chin +- Alessandro Coglio +- Eric McCarthy +- Jon Pavlik +- Damir Shamanaev +- Damon Sicore +- Howard Wu + +## Status + +DRAFT + +# Summary + +This RFC proposes the addition of type aliases to Leo, +i.e. identifiers that abbreviate types and can be used wherever the latter can be used. +A new top-level construct is proposed to define type aliases; no circularities are allowed. +Type aliases are expanded away during compilation. + +# Motivation + +Many programming languages provide the ability to create aliases (i.e. synonyms) of types, such as C's `typedef`. +The purpose may be to abbreviate a longer type, +such as an alias `matrix` for `[i32; (3, 3)]` in an application in which 3x3 matrices of 32-bit integers are relevant +(e.g. for 3-D rotations, even though fractional numbers may be more realistic). +The purpose may also be to clarify the purpose and use of an existing type, +such as an alias `balance` for `u64` in an application that keeps track of balances. + +The initial motivation that inspired this RFC (along with other RFCs) +was the ability to have a type `string` for strings. +Strings are arrays of characters according to RFC 001. +With the array types of unspecified size proposed in RFC 006, +`[char; _]` becomes a generic type for strings, which is desirable to alias with `string`. + +# Design + +## Syntax + +The ABNF grammar changes as follows: +```ts +; modified rule: +keyword = ... + / %s"true" + / %s"type" ; new + / %s"u8" + / ... + +; new rule: +type-alias-declaration = %s"type" identifier "=" type ";" + +; modified rule: +declaration = import-declaration + / function-declaration + / circuit-declaration + / constant-declaration + / type-alias-declaration ; new +``` + +A type alias declaration introduces the identifier to stand for the type. +Only top-level type alias declarations are supported; +they are not supported inside functions or circuit types. + +## Semantics + +There must be no direct or indirect circularity in the type aliases. +That is, it must be possible to expand all the type aliases away, +obtaining an equivalent program without any type aliases. + +Note that the built-in `Self` is a bit like a type alias, standing for the enclosing circuit type; +and `Self` is replaced with the enclosing circuit type during canonicalization. +Thus, canonicalization could be a natural place to expand user-defined type aliases; +after all, type aliases introduce multiple ways to denote the same types +(and not just via direct aliasing, but also via indirect aliasing, or via aliasing of components), +and canonicalization serves exactly to reduce multiple ways to say the same thing to one canonical way. + +On the other hand, expanding type aliases is more complicated than the current canonicalization transformations, +which are all local and relatively simple. +Expanding type aliases requires not only checking for circularities, +but also to take into account references to type aliases from import declarations. +For this reason, we may perform type alias expansion after canonicalization, +such as just before type checking and inference. +We could also make the expansion a part of the type checking and inference process, +which already transforms the program by inferring missing types, +so it could also expand type aliases away. + +In any case, it seems beneficial to expand type aliases away +(whether during canonicalization or as part or preamble to type checking and inference) +prior to performing more processing of the program for eventual compilation to R1CS. + +## Examples + +The aforementioned 3x3 matrix example could be written as follows: +```ts +type matrix = [u32; (3, 3)]; + +function matrix_multiply(x: matrix, y: matrix) -> matrix { + ... +} +``` + +The aforementioned balance example could be written as follows: +```ts +type balance = u64; + +function f(...) -> (..., balance, ...) { + ... +} +``` + +The aforementioned string example could be written as follows: +```ts +type string = [char; _]; + +function f(str: string) -> ... { + ... +} +``` + +# Drawbacks + +As other extensions of the language, this makes things inherently a bit more complicated. + +# Effect on Ecosystem + +None; this is just a convenience for the Leo developer. + +# Alternatives + +An alternative to creating a type alias +```ts +type T = U; +``` +is to create a circuit type +```ts +circuit T { get: U } +``` +that contains a single member variable. + +This is clearly not equivalent to a type alias, because it involves conversions between `T` and `U` +```ts +T { get: u } // convert u:U to T +t.get // convert t:T to U +``` +whereas a type alias involves no conversions: +if `T` is an alias of `U`, then `T` and `U` are the same type, +more precisely two syntactically different ways to designate the same semantic type. + +While the conversions generally cause overhead in traditional programming languages, +this may not be the case for Leo's compilation to R1CS, +in which everything is flattened, including member variables of circuit types. +Thus, it may be the case that the circuit `T` above reduces to just its member `U` in R1CS. + +It might also be argued that wrapping a type into a one-member-variable circuit type +could be a better practice than aliasing the type, to enforce better type separation and safety. + +We need to consider the pros and cons of the two approaches, +particularly in light of Leo's non-traditional compilation target. diff --git a/docs/rfc/008-built-in-declarations.md b/docs/rfc/008-built-in-declarations.md new file mode 100644 index 0000000000..4f710ec3a0 --- /dev/null +++ b/docs/rfc/008-built-in-declarations.md @@ -0,0 +1,82 @@ +# Leo RFC 008: Built-in Declarations + +## Authors + +- Max Bruce +- Collin Chin +- Alessandro Coglio +- Eric McCarthy +- Jon Pavlik +- Damir Shamanaev +- Damon Sicore +- Howard Wu + +## Status + +DRAFT + +# Summary + +This RFC proposes a framework for making certain (top-level) declarations (e.g. type aliases) +available in every Leo program without the need to explicitly write those declarations. +These may be hardwired into the language, or provided by standard libraries/packages; +in the latter case, the libraries may be either implicitly imported or required to be explicitly imported. + +# Motivation + +It is common for programming languages to provide predefined types, functions, etc. +that can be readily used in programs. +The initial motivation for this in Leo was to have a type alias `string` for character arrays of unspecified sizes +(array types of unspecified sizes and type aliases are discussed in separate RFCs), +but the feature is clearly more general. + +# Design + +Leo supports four kinds of top-level declarations: +- Import declarations. +- Function declarations. +- Circuit type declarations. +- Global constant declarations. +- Type alias declarations. (Proposed in a separate RFC.) + +Leaving import declarations aside for the moment since they are "meta" in some sense +(as they bring in names of entities declared elsewhere), +it may make sense for any of the four kinds of declarations above to have built-in instances, +i.e. we could have some built-in functions, circuit types, global constants, and type aliases. +This is why this RFC talks of built-in declarations, more broadly than just built-in type aliases that inspired it. + +The built-in status of the envisioned declarations could be achieved in slightly different ways: +1. Their names could be simply available in any program, + without any explicit declaration found anywhere for them. +2. They could be declared in some core library files explicitly, + and be available in any program without needing to be explicitly import them, + like `java.lang.String` in Java or `std::Option` in Rust. +3. They could be declared in some core library files explicitly, + and be available only in programs that explicitly import them. + +From a user's perspective, there is not a lot of difference between cases 1 and 2 above: +in both cases, the names are available; the only difference is that in case 2 the user can see the declaration somewhere. + +Also note that case 2 could be seen as having an implicit (i.e. built-in) import of the library/libraries in question. +Again, imports are "meta" in this context, and what counts are really the other kinds of declarations. + +In cases 2 and 3, a related but somewhat independent issue is whether those declarations have Leo definitions or not. +The Leo library already includes functions like the one for BLAKE2s that are not defined in Leo, +but rather "natively" in Rust/R1CS. + +# Drawbacks + +This does not seem to bring any drawbacks. + +# Effect on Ecosystem + +This may interact with libraries and packages in some way, +if we go with case 2 or 3 above. +But it should be not much different from regular libraries/packages. + +# Alternatives + +The 'Design' section above currently discusses a few alternatives, +rather than prescribing a defined approach. +When consensus is reached on one of the alternatives discussed there, +the others will be moved to this section. diff --git a/grammar/Cargo.toml b/grammar/Cargo.toml index d9fc3e5b9c..1e7248fc79 100644 --- a/grammar/Cargo.toml +++ b/grammar/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "leo-abnf" -version = "1.5.2" +version = "1.5.3" authors = [ "The Aleo Team " ] description = "ABNF to Markdown converter for the Leo programming language" homepage = "https://aleo.org" diff --git a/grammar/README.md b/grammar/README.md index b22bd5ecf0..364002f1eb 100644 --- a/grammar/README.md +++ b/grammar/README.md @@ -511,7 +511,7 @@ rest-of-block-comment = "*" rest-of-block-comment-after-star / not-star rest-of-block-comment ``` -Go to: _[rest-of-block-comment](#user-content-rest-of-block-comment), [rest-of-block-comment-after-star](#user-content-rest-of-block-comment-after-star), [not-star](#user-content-not-star)_; +Go to: _[not-star](#user-content-not-star), [rest-of-block-comment](#user-content-rest-of-block-comment), [rest-of-block-comment-after-star](#user-content-rest-of-block-comment-after-star)_; @@ -521,7 +521,7 @@ rest-of-block-comment-after-star = "/" / not-star-or-slash rest-of-block-comment ``` -Go to: _[not-star-or-slash](#user-content-not-star-or-slash), [rest-of-block-comment](#user-content-rest-of-block-comment), [rest-of-block-comment-after-star](#user-content-rest-of-block-comment-after-star)_; +Go to: _[rest-of-block-comment-after-star](#user-content-rest-of-block-comment-after-star), [not-star-or-slash](#user-content-not-star-or-slash), [rest-of-block-comment](#user-content-rest-of-block-comment)_; @@ -772,7 +772,7 @@ character-literal-element = not-single-quote-or-backslash / unicode-character-escape ``` -Go to: _[simple-character-escape](#user-content-simple-character-escape), [unicode-character-escape](#user-content-unicode-character-escape), [not-single-quote-or-backslash](#user-content-not-single-quote-or-backslash), [ascii-character-escape](#user-content-ascii-character-escape)_; +Go to: _[unicode-character-escape](#user-content-unicode-character-escape), [simple-character-escape](#user-content-simple-character-escape), [not-single-quote-or-backslash](#user-content-not-single-quote-or-backslash), [ascii-character-escape](#user-content-ascii-character-escape)_; @@ -827,7 +827,7 @@ simple-character-escape = single-quote-escape / null-character-escape ``` -Go to: _[carriage-return-escape](#user-content-carriage-return-escape), [single-quote-escape](#user-content-single-quote-escape), [backslash-escape](#user-content-backslash-escape), [line-feed-escape](#user-content-line-feed-escape), [horizontal-tab-escape](#user-content-horizontal-tab-escape), [null-character-escape](#user-content-null-character-escape), [double-quote-escape](#user-content-double-quote-escape)_; +Go to: _[horizontal-tab-escape](#user-content-horizontal-tab-escape), [backslash-escape](#user-content-backslash-escape), [null-character-escape](#user-content-null-character-escape), [line-feed-escape](#user-content-line-feed-escape), [single-quote-escape](#user-content-single-quote-escape), [double-quote-escape](#user-content-double-quote-escape), [carriage-return-escape](#user-content-carriage-return-escape)_; @@ -835,7 +835,7 @@ Go to: _[carriage-return-escape](#user-content-carriage-return-escape), [single- ascii-character-escape = %s"\x" octal-digit hexadecimal-digit ``` -Go to: _[hexadecimal-digit](#user-content-hexadecimal-digit), [octal-digit](#user-content-octal-digit)_; +Go to: _[octal-digit](#user-content-octal-digit), [hexadecimal-digit](#user-content-hexadecimal-digit)_; @@ -863,7 +863,7 @@ string-literal-element = not-double-quote-or-backslash / unicode-character-escape ``` -Go to: _[not-double-quote-or-backslash](#user-content-not-double-quote-or-backslash), [simple-character-escape](#user-content-simple-character-escape), [unicode-character-escape](#user-content-unicode-character-escape), [ascii-character-escape](#user-content-ascii-character-escape)_; +Go to: _[not-double-quote-or-backslash](#user-content-not-double-quote-or-backslash), [simple-character-escape](#user-content-simple-character-escape), [ascii-character-escape](#user-content-ascii-character-escape), [unicode-character-escape](#user-content-unicode-character-escape)_; The ones above are all the atomic literals @@ -883,7 +883,7 @@ atomic-literal = untyped-literal / string-literal ``` -Go to: _[string-literal](#user-content-string-literal), [product-group-literal](#user-content-product-group-literal), [unsigned-literal](#user-content-unsigned-literal), [field-literal](#user-content-field-literal), [address-literal](#user-content-address-literal), [boolean-literal](#user-content-boolean-literal), [untyped-literal](#user-content-untyped-literal), [character-literal](#user-content-character-literal), [signed-literal](#user-content-signed-literal)_; +Go to: _[signed-literal](#user-content-signed-literal), [unsigned-literal](#user-content-unsigned-literal), [field-literal](#user-content-field-literal), [product-group-literal](#user-content-product-group-literal), [boolean-literal](#user-content-boolean-literal), [address-literal](#user-content-address-literal), [string-literal](#user-content-string-literal), [untyped-literal](#user-content-untyped-literal), [character-literal](#user-content-character-literal)_; After defining the (mostly) alphanumeric tokens above, @@ -927,7 +927,17 @@ token = keyword / symbol ``` -Go to: _[atomic-literal](#user-content-atomic-literal), [identifier](#user-content-identifier), [symbol](#user-content-symbol), [package-name](#user-content-package-name), [annotation-name](#user-content-annotation-name), [keyword](#user-content-keyword)_; +Go to: _[atomic-literal](#user-content-atomic-literal), [package-name](#user-content-package-name), [annotation-name](#user-content-annotation-name), [symbol](#user-content-symbol), [identifier](#user-content-identifier), [keyword](#user-content-keyword)_; + + +Tokens, comments, and whitespace are lexemes, i.e. lexical units. + + +```abnf +lexeme = token / comment / whitespace +``` + +Go to: _[whitespace](#user-content-whitespace), [comment](#user-content-comment), [token](#user-content-token)_; @@ -984,7 +994,7 @@ group-type = %s"group" arithmetic-type = integer-type / field-type / group-type ``` -Go to: _[field-type](#user-content-field-type), [group-type](#user-content-group-type), [integer-type](#user-content-integer-type)_; +Go to: _[integer-type](#user-content-integer-type), [field-type](#user-content-field-type), [group-type](#user-content-group-type)_; The arithmetic types, along with the boolean, address, and character types, @@ -1050,7 +1060,7 @@ or a tuple of one or more dimensions. array-type = "[" type ";" array-dimensions "]" ``` -Go to: _[array-dimensions](#user-content-array-dimensions), [type](#user-content-type)_; +Go to: _[type](#user-content-type), [array-dimensions](#user-content-array-dimensions)_; @@ -1071,7 +1081,7 @@ i.e. types whose values contain (sub-)values aggregate-type = tuple-type / array-type / circuit-type ``` -Go to: _[tuple-type](#user-content-tuple-type), [array-type](#user-content-array-type), [circuit-type](#user-content-circuit-type)_; +Go to: _[circuit-type](#user-content-circuit-type), [tuple-type](#user-content-tuple-type), [array-type](#user-content-array-type)_; Scalar and aggregate types form all the types. @@ -1081,7 +1091,7 @@ Scalar and aggregate types form all the types. type = scalar-type / aggregate-type ``` -Go to: _[aggregate-type](#user-content-aggregate-type), [scalar-type](#user-content-scalar-type)_; +Go to: _[scalar-type](#user-content-scalar-type), [aggregate-type](#user-content-aggregate-type)_; The lexical grammar given earlier defines product group literals. @@ -1159,7 +1169,7 @@ primary-expression = identifier / circuit-expression ``` -Go to: _[tuple-expression](#user-content-tuple-expression), [literal](#user-content-literal), [expression](#user-content-expression), [circuit-expression](#user-content-circuit-expression), [identifier](#user-content-identifier), [array-expression](#user-content-array-expression)_; +Go to: _[expression](#user-content-expression), [array-expression](#user-content-array-expression), [literal](#user-content-literal), [identifier](#user-content-identifier), [circuit-expression](#user-content-circuit-expression), [tuple-expression](#user-content-tuple-expression)_; Tuple expressions construct tuples. @@ -1220,7 +1230,7 @@ Go to: _[expression](#user-content-expression), [array-dimensions](#user-content array-construction = array-inline-construction / array-repeat-construction ``` -Go to: _[array-repeat-construction](#user-content-array-repeat-construction), [array-inline-construction](#user-content-array-inline-construction)_; +Go to: _[array-inline-construction](#user-content-array-inline-construction), [array-repeat-construction](#user-content-array-repeat-construction)_; @@ -1248,7 +1258,7 @@ circuit-construction = circuit-type "{" "}" ``` -Go to: _[circuit-inline-element](#user-content-circuit-inline-element), [circuit-type](#user-content-circuit-type)_; +Go to: _[circuit-type](#user-content-circuit-type), [circuit-inline-element](#user-content-circuit-inline-element)_; @@ -1307,7 +1317,7 @@ postfix-expression = primary-expression / postfix-expression "[" [expression] ".." [expression] "]" ``` -Go to: _[circuit-type](#user-content-circuit-type), [postfix-expression](#user-content-postfix-expression), [primary-expression](#user-content-primary-expression), [identifier](#user-content-identifier), [function-arguments](#user-content-function-arguments), [natural](#user-content-natural), [expression](#user-content-expression)_; +Go to: _[natural](#user-content-natural), [identifier](#user-content-identifier), [circuit-type](#user-content-circuit-type), [primary-expression](#user-content-primary-expression), [function-arguments](#user-content-function-arguments), [postfix-expression](#user-content-postfix-expression), [expression](#user-content-expression)_; Unary operators have the highest operator precedence. @@ -1321,7 +1331,7 @@ unary-expression = postfix-expression / "-" unary-expression ``` -Go to: _[unary-expression](#user-content-unary-expression), [postfix-expression](#user-content-postfix-expression)_; +Go to: _[postfix-expression](#user-content-postfix-expression), [unary-expression](#user-content-unary-expression)_; Next in the operator precedence is exponentiation, @@ -1347,7 +1357,7 @@ multiplicative-expression = exponential-expression / multiplicative-expression "/" exponential-expression ``` -Go to: _[multiplicative-expression](#user-content-multiplicative-expression), [exponential-expression](#user-content-exponential-expression)_; +Go to: _[exponential-expression](#user-content-exponential-expression), [multiplicative-expression](#user-content-multiplicative-expression)_; Then there are addition and subtraction, both left-assocative. @@ -1359,7 +1369,7 @@ additive-expression = multiplicative-expression / additive-expression "-" multiplicative-expression ``` -Go to: _[multiplicative-expression](#user-content-multiplicative-expression), [additive-expression](#user-content-additive-expression)_; +Go to: _[additive-expression](#user-content-additive-expression), [multiplicative-expression](#user-content-multiplicative-expression)_; Next in the precedence order are ordering relations. @@ -1398,7 +1408,7 @@ conjunctive-expression = equality-expression / conjunctive-expression "&&" equality-expression ``` -Go to: _[conjunctive-expression](#user-content-conjunctive-expression), [equality-expression](#user-content-equality-expression)_; +Go to: _[equality-expression](#user-content-equality-expression), [conjunctive-expression](#user-content-conjunctive-expression)_; Next come disjunctive expressions, left-associative. @@ -1409,7 +1419,7 @@ disjunctive-expression = conjunctive-expression / disjunctive-expression "||" conjunctive-expression ``` -Go to: _[disjunctive-expression](#user-content-disjunctive-expression), [conjunctive-expression](#user-content-conjunctive-expression)_; +Go to: _[conjunctive-expression](#user-content-conjunctive-expression), [disjunctive-expression](#user-content-disjunctive-expression)_; Finally we have conditional expressions. @@ -1422,7 +1432,7 @@ conditional-expression = disjunctive-expression ":" conditional-expression ``` -Go to: _[expression](#user-content-expression), [conditional-expression](#user-content-conditional-expression), [disjunctive-expression](#user-content-disjunctive-expression)_; +Go to: _[expression](#user-content-expression), [disjunctive-expression](#user-content-disjunctive-expression), [conditional-expression](#user-content-conditional-expression)_; Those above are all the expressions. @@ -1455,7 +1465,7 @@ statement = expression-statement / block ``` -Go to: _[assignment-statement](#user-content-assignment-statement), [expression-statement](#user-content-expression-statement), [conditional-statement](#user-content-conditional-statement), [block](#user-content-block), [loop-statement](#user-content-loop-statement), [constant-declaration](#user-content-constant-declaration), [console-statement](#user-content-console-statement), [variable-declaration](#user-content-variable-declaration), [return-statement](#user-content-return-statement)_; +Go to: _[constant-declaration](#user-content-constant-declaration), [block](#user-content-block), [variable-declaration](#user-content-variable-declaration), [conditional-statement](#user-content-conditional-statement), [return-statement](#user-content-return-statement), [assignment-statement](#user-content-assignment-statement), [expression-statement](#user-content-expression-statement), [loop-statement](#user-content-loop-statement), [console-statement](#user-content-console-statement)_; @@ -1498,7 +1508,7 @@ variable-declaration = %s"let" identifier-or-identifiers [ ":" type ] "=" expression ";" ``` -Go to: _[expression](#user-content-expression), [identifier-or-identifiers](#user-content-identifier-or-identifiers), [type](#user-content-type)_; +Go to: _[type](#user-content-type), [expression](#user-content-expression), [identifier-or-identifiers](#user-content-identifier-or-identifiers)_; @@ -1507,7 +1517,7 @@ constant-declaration = %s"const" identifier-or-identifiers [ ":" type ] "=" expression ";" ``` -Go to: _[type](#user-content-type), [expression](#user-content-expression), [identifier-or-identifiers](#user-content-identifier-or-identifiers)_; +Go to: _[identifier-or-identifiers](#user-content-identifier-or-identifiers), [type](#user-content-type), [expression](#user-content-expression)_; @@ -1530,7 +1540,7 @@ Note that blocks are required in all branches, not merely statements. branch = %s"if" expression block ``` -Go to: _[expression](#user-content-expression), [block](#user-content-block)_; +Go to: _[block](#user-content-block), [expression](#user-content-expression)_; @@ -1596,7 +1606,7 @@ console-call = assert-call / print-call ``` -Go to: _[print-call](#user-content-print-call), [assert-call](#user-content-assert-call)_; +Go to: _[assert-call](#user-content-assert-call), [print-call](#user-content-print-call)_; @@ -1638,7 +1648,7 @@ annotation = annotation-name [ "(" identifier *( "," identifier ) ")" ] ``` -Go to: _[identifier](#user-content-identifier), [annotation-name](#user-content-annotation-name)_; +Go to: _[annotation-name](#user-content-annotation-name), [identifier](#user-content-identifier)_; A function declaration defines a function. @@ -1655,7 +1665,7 @@ function-declaration = *annotation %s"function" identifier block ``` -Go to: _[type](#user-content-type), [identifier](#user-content-identifier), [function-parameters](#user-content-function-parameters), [block](#user-content-block)_; +Go to: _[block](#user-content-block), [identifier](#user-content-identifier), [function-parameters](#user-content-function-parameters), [type](#user-content-type)_; @@ -1665,7 +1675,7 @@ function-parameters = self-parameter / function-inputs ``` -Go to: _[self-parameter](#user-content-self-parameter), [function-inputs](#user-content-function-inputs)_; +Go to: _[function-inputs](#user-content-function-inputs), [self-parameter](#user-content-self-parameter)_; @@ -1706,7 +1716,7 @@ member-variable-declarations = *( identifier ":" type ( "," / ";" ) ) identifier ":" type ( [ "," ] / ";" ) ``` -Go to: _[identifier](#user-content-identifier), [type](#user-content-type)_; +Go to: _[type](#user-content-type), [identifier](#user-content-identifier)_; A circuit member function declaration consists of a function declaration. @@ -1756,7 +1766,7 @@ by using an explicit package name before the package path. import-declaration = %s"import" package-name "." package-path ";" ``` -Go to: _[package-name](#user-content-package-name), [package-path](#user-content-package-path)_; +Go to: _[package-path](#user-content-package-path), [package-name](#user-content-package-name)_; @@ -1782,7 +1792,7 @@ declaration = import-declaration / constant-declaration ``` -Go to: _[circuit-declaration](#user-content-circuit-declaration), [constant-declaration](#user-content-constant-declaration), [import-declaration](#user-content-import-declaration), [function-declaration](#user-content-function-declaration)_; +Go to: _[function-declaration](#user-content-function-declaration), [circuit-declaration](#user-content-circuit-declaration), [constant-declaration](#user-content-constant-declaration), [import-declaration](#user-content-import-declaration)_; diff --git a/grammar/abnf-grammar.txt b/grammar/abnf-grammar.txt index 124a0f1f37..ee4dc083fa 100644 --- a/grammar/abnf-grammar.txt +++ b/grammar/abnf-grammar.txt @@ -611,6 +611,10 @@ token = keyword / annotation-name / symbol +; Tokens, comments, and whitespace are lexemes, i.e. lexical units. + +lexeme = token / comment / whitespace + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Syntactic Grammar diff --git a/imports/Cargo.toml b/imports/Cargo.toml index 2770edf50b..5e9ede2cb7 100644 --- a/imports/Cargo.toml +++ b/imports/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "leo-imports" -version = "1.5.2" +version = "1.5.3" authors = [ "The Aleo Team " ] description = "Import parser for Leo program package dependencies" homepage = "https://aleo.org" @@ -19,15 +19,15 @@ edition = "2018" [dependencies.leo-ast] path = "../ast" -version = "1.5.2" +version = "1.5.3" [dependencies.leo-asg] path = "../asg" -version = "1.5.2" +version = "1.5.3" [dependencies.leo-parser] path = "../parser" -version = "1.5.2" +version = "1.5.3" [dependencies.indexmap] version = "1.7.0" diff --git a/input/Cargo.toml b/input/Cargo.toml index 3c98793c16..448b9028e4 100644 --- a/input/Cargo.toml +++ b/input/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "leo-input" -version = "1.5.2" +version = "1.5.3" authors = [ "The Aleo Team " ] description = "Input parser of the Leo programming language" homepage = "https://aleo.org" diff --git a/leo/logger.rs b/leo/logger.rs index b2f639ef01..f7f145a4c2 100644 --- a/leo/logger.rs +++ b/leo/logger.rs @@ -218,6 +218,11 @@ pub fn init_logger(_app_name: &'static str, verbosity: usize) -> Result<()> { Err(_) => return Err(anyhow::anyhow!("Error: Failed to enable ansi_support")), }; + use tracing_subscriber::fmt::writer::MakeWriterExt; + + let stderr = std::io::stderr.with_max_level(tracing::Level::WARN); + let mk_writer = stderr.or_else(std::io::stdout); + let subscriber = FmtSubscriber::builder() // all spans/events with a level higher than TRACE (e.g, debug, info, warn, etc.) // will be written to stdout. @@ -227,6 +232,7 @@ pub fn init_logger(_app_name: &'static str, verbosity: usize) -> Result<()> { 2 => tracing::Level::DEBUG, _ => tracing::Level::TRACE }) + .with_writer(mk_writer) .without_time() .with_target(false) .event_format(Format::default()) diff --git a/leo/main.rs b/leo/main.rs index e10afcb6fc..4ddf251f19 100644 --- a/leo/main.rs +++ b/leo/main.rs @@ -39,6 +39,7 @@ use commands::{ }; use anyhow::Result; +use colored::Colorize; use std::{path::PathBuf, process::exit}; use structopt::{clap::AppSettings, StructOpt}; @@ -233,7 +234,20 @@ fn handle_error(res: Result) -> T { match res { Ok(t) => t, Err(err) => { - eprintln!("Error: {}", err); + eprintln!( + "{} {}", + "Error:".bold().red(), + err.to_string() + .lines() + .enumerate() + .map(|(i, l)| if i == 0 { + l.bold().red().to_string() + } else { + l.to_string() + }) + .collect::>() + .join("\n") + ); exit(1); } } diff --git a/linter/Cargo.toml b/linter/Cargo.toml index f01bd3ffbc..c69dba5d89 100644 --- a/linter/Cargo.toml +++ b/linter/Cargo.toml @@ -2,7 +2,7 @@ dependencies = { } [package] name = "leo-linter" -version = "1.5.2" +version = "1.5.3" authors = [ "The Aleo Team " ] description = "Linter of the Leo programming language" homepage = "https://aleo.org" diff --git a/package/Cargo.toml b/package/Cargo.toml index 43f645d7d9..e8a5e81059 100644 --- a/package/Cargo.toml +++ b/package/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "leo-package" -version = "1.5.2" +version = "1.5.3" authors = [ "The Aleo Team " ] description = "Package parser of the Leo programming language" homepage = "https://aleo.org" diff --git a/parser/Cargo.toml b/parser/Cargo.toml index 55c6125d5d..10529e693a 100644 --- a/parser/Cargo.toml +++ b/parser/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "leo-parser" -version = "1.5.2" +version = "1.5.3" authors = [ "The Aleo Team " ] description = "AST generated by pest from the Leo grammar rules" homepage = "https://aleo.org" @@ -24,7 +24,7 @@ harness = false [dependencies.leo-ast] path = "../ast" -version = "1.5.2" +version = "1.5.3" [dependencies.lazy_static] version = "1.3.0" diff --git a/parser/src/parser/statement.rs b/parser/src/parser/statement.rs index d60d3e12bb..1b82145f43 100644 --- a/parser/src/parser/statement.rs +++ b/parser/src/parser/statement.rs @@ -277,13 +277,12 @@ impl ParserContext { let expr = self.parse_expression()?; ConsoleFunction::Assert(expr) } - "debug" => ConsoleFunction::Debug(self.parse_console_args()?), "error" => ConsoleFunction::Error(self.parse_console_args()?), "log" => ConsoleFunction::Log(self.parse_console_args()?), x => { return Err(SyntaxError::unexpected_ident( &x, - &["assert", "debug", "error", "log"], + &["assert", "error", "log"], &function.span, )); } diff --git a/state/Cargo.toml b/state/Cargo.toml index 8e3946214d..13a4c99a12 100644 --- a/state/Cargo.toml +++ b/state/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "leo-state" -version = "1.5.2" +version = "1.5.3" authors = [ "The Aleo Team " ] description = "State parser of the Leo programming language" homepage = "https://aleo.org" @@ -19,11 +19,11 @@ edition = "2018" [dependencies.leo-input] path = "../input" -version = "1.5.2" +version = "1.5.3" [dependencies.leo-ast] path = "../ast" -version = "1.5.2" +version = "1.5.3" [dependencies.snarkvm-algorithms] version = "0.7.4" diff --git a/synthesizer/Cargo.toml b/synthesizer/Cargo.toml index 7daf23a580..4a84f46cb7 100644 --- a/synthesizer/Cargo.toml +++ b/synthesizer/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "leo-synthesizer" -version = "1.5.2" +version = "1.5.3" authors = [ "The Aleo Team " ] description = "Circuit synthesizer of the Leo programming language" homepage = "https://aleo.org" diff --git a/test-framework/Cargo.toml b/test-framework/Cargo.toml index 28c8aabc0a..fa5440225b 100644 --- a/test-framework/Cargo.toml +++ b/test-framework/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "leo-test-framework" -version = "1.5.2" +version = "1.5.3" authors = [ "The Aleo Team " ] description = "Leo testing framework" homepage = "https://aleo.org" diff --git a/tests/compiler/address/branch.leo b/tests/compiler/address/branch.leo new file mode 100644 index 0000000000..5b2023a43b --- /dev/null +++ b/tests/compiler/address/branch.leo @@ -0,0 +1,15 @@ +/* +namespace: Compile +expectation: Pass +input_file: inputs/branch.in +*/ + + +function main (x: address, y: bool) -> bool { + let z = aleo18cw5zdez3zhypev3tnfhmwvhre9ramwle4up947gcyy5rnmjw5yqn93wsr; + if y { + z = aleo1f2gs8g0qpumlgzpvmkw3q07y6xrwsdr0lqsu9h9fgnh8d7e44v9qhpgpkj; + } + + return z == aleo1f2gs8g0qpumlgzpvmkw3q07y6xrwsdr0lqsu9h9fgnh8d7e44v9qhpgpkj; +} \ No newline at end of file diff --git a/tests/compiler/address/index.leo b/tests/compiler/address/index.leo new file mode 100644 index 0000000000..5d7cb2b389 --- /dev/null +++ b/tests/compiler/address/index.leo @@ -0,0 +1,12 @@ +/* +namespace: Compile +expectation: Pass +input_file: inputs/index.in +*/ + +function main (x: u32) -> bool { + const y = [aleo1x0rh2cudq93fhukrsce8sgvcphddv4qs0clph64stpg0hstfds9qjvxcg6; 3]; + let z = y[x]; + + return z == y[0]; +} \ No newline at end of file diff --git a/tests/compiler/address/inputs/branch.in b/tests/compiler/address/inputs/branch.in new file mode 100644 index 0000000000..24e6b338e0 --- /dev/null +++ b/tests/compiler/address/inputs/branch.in @@ -0,0 +1,6 @@ +[main] +x: address = aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8; +y: bool = true; + +[registers] +a: bool = false; \ No newline at end of file diff --git a/tests/compiler/address/inputs/index.in b/tests/compiler/address/inputs/index.in new file mode 100644 index 0000000000..5e701ee7a6 --- /dev/null +++ b/tests/compiler/address/inputs/index.in @@ -0,0 +1,5 @@ +[main] +x: u32 = 0; + +[registers] +a: bool = false; \ No newline at end of file diff --git a/tests/compiler/console/debug.leo b/tests/compiler/console/debug.leo deleted file mode 100644 index 4b24b6e5fc..0000000000 --- a/tests/compiler/console/debug.leo +++ /dev/null @@ -1,10 +0,0 @@ -/* -namespace: Compile -expectation: Pass -input_file: input/dummy.in -*/ - -function main(y: bool) -> bool { - console.debug("hello debug"); - return y == true; -} diff --git a/tests/compiler/function/duplicate_definition_fail.leo b/tests/compiler/function/duplicate_definition_fail.leo index 2909fae2b1..43ec30e787 100644 --- a/tests/compiler/function/duplicate_definition_fail.leo +++ b/tests/compiler/function/duplicate_definition_fail.leo @@ -1,15 +1,14 @@ /* namespace: Compile expectation: Fail -input_file: input/integers.in +input_file: input/dummy.in */ -function main(a: u32) -> u32 { +function main() { console.log("{}", 1u8); - return 10u32; } function main() { - console.log("{}", 2u8); + console.log("{}", 2u8); } diff --git a/tests/expectations/compiler/compiler/address/branch.leo.out b/tests/expectations/compiler/compiler/address/branch.leo.out new file mode 100644 index 0000000000..a4c062bc76 --- /dev/null +++ b/tests/expectations/compiler/compiler/address/branch.leo.out @@ -0,0 +1,21 @@ +--- +namespace: Compile +expectation: Pass +outputs: + - circuit: + num_public_variables: 0 + num_private_variables: 1024 + num_constraints: 1536 + at: 5afd1d58b6826912fe5cba06b60d9a7debdbad9e922b8a78ed49f7a7ca0ac65e + bt: db77c3470cf1b3c80c2e3b1b3ddc59d9891912489bfcf39b7f67c2f314ca7f6d + ct: d0993682df5b495f4a6784882e0f007dbc378adb35007d250e2c098975f4d32e + output: + - input_file: inputs/branch.in + output: + registers: + a: + type: bool + value: "true" + initial_ast: a7748573e4731753b76889c6d4c28e9589e114860a163da87957cf20b916f733 + canonicalized_ast: a7748573e4731753b76889c6d4c28e9589e114860a163da87957cf20b916f733 + type_inferenced_ast: af3663710ad6278c3d2e28a753d62084505746cd49de11949fe5e8e390ffcc60 diff --git a/tests/expectations/compiler/compiler/address/index.leo.out b/tests/expectations/compiler/compiler/address/index.leo.out new file mode 100644 index 0000000000..b4cda33ee6 --- /dev/null +++ b/tests/expectations/compiler/compiler/address/index.leo.out @@ -0,0 +1,21 @@ +--- +namespace: Compile +expectation: Pass +outputs: + - circuit: + num_public_variables: 0 + num_private_variables: 1694 + num_constraints: 2719 + at: f9a9bc8304df327c7b16f088b61ac518fb3a7b6457ccc35a1ab9eab4565a1981 + bt: 045eba0fdd405714f788492fd5914b053e0ece622e9a542270d8cfe85c0ee291 + ct: e8fa4a33a657c70a7cecc7e9b284157b369b7ea57879948e108daf93e778551c + output: + - input_file: inputs/index.in + output: + registers: + a: + type: bool + value: "true" + initial_ast: 8934e4c1d645f6f98fe59f48bbf687623e811c99e504e87c6989bc00af62194a + canonicalized_ast: 8934e4c1d645f6f98fe59f48bbf687623e811c99e504e87c6989bc00af62194a + type_inferenced_ast: 70af835aeaec1d5bc1c4a3186635260ff44743e0d3a7aa5ac9f2c98ec03bd23e diff --git a/tests/expectations/compiler/compiler/array/variable_slice_fail.leo.out b/tests/expectations/compiler/compiler/array/variable_slice_fail.leo.out index 307885a20d..b38b3bbbf2 100644 --- a/tests/expectations/compiler/compiler/array/variable_slice_fail.leo.out +++ b/tests/expectations/compiler/compiler/array/variable_slice_fail.leo.out @@ -2,4 +2,4 @@ namespace: Compile expectation: Fail outputs: - - " --> compiler-test:6:19\n |\n 6 | const x = a[i..10];\n | ^^^^^^^^\n |\n = array size cannot be inferred, add explicit types" + - " --> compiler-test:7:17\n |\n 7 | console.debug(\"{}\", x);\n | ^^^^^\n |\n = expected identifier 'assert', 'error', 'log' -- got 'debug'" diff --git a/tests/expectations/compiler/compiler/core/core_circuit_star_fail.leo.out b/tests/expectations/compiler/compiler/core/core_circuit_star_fail.leo.out index 104faae420..9bb7631c2d 100644 --- a/tests/expectations/compiler/compiler/core/core_circuit_star_fail.leo.out +++ b/tests/expectations/compiler/compiler/core/core_circuit_star_fail.leo.out @@ -2,4 +2,4 @@ namespace: Compile expectation: Fail outputs: - - " --> :0:0\n |\n |\n |\n = failed to resolve import: 'core'" + - " --> :0:0\n |\n |\n = failed to resolve import: 'core'" diff --git a/tests/expectations/compiler/compiler/core/core_package_invalid.leo.out b/tests/expectations/compiler/compiler/core/core_package_invalid.leo.out index 104faae420..9bb7631c2d 100644 --- a/tests/expectations/compiler/compiler/core/core_package_invalid.leo.out +++ b/tests/expectations/compiler/compiler/core/core_package_invalid.leo.out @@ -2,4 +2,4 @@ namespace: Compile expectation: Fail outputs: - - " --> :0:0\n |\n |\n |\n = failed to resolve import: 'core'" + - " --> :0:0\n |\n |\n = failed to resolve import: 'core'" diff --git a/tests/expectations/compiler/compiler/core/core_unstable_package_invalid.leo.out b/tests/expectations/compiler/compiler/core/core_unstable_package_invalid.leo.out index 4fb07b9d05..2493893de3 100644 --- a/tests/expectations/compiler/compiler/core/core_unstable_package_invalid.leo.out +++ b/tests/expectations/compiler/compiler/core/core_unstable_package_invalid.leo.out @@ -2,4 +2,4 @@ namespace: Compile expectation: Fail outputs: - - " --> :0:0\n |\n |\n |\n = failed to resolve import: 'core.unstable'" + - " --> :0:0\n |\n |\n = failed to resolve import: 'core.unstable'" diff --git a/tests/expectations/compiler/compiler/function/duplicate_definition_fail.leo.out b/tests/expectations/compiler/compiler/function/duplicate_definition_fail.leo.out index 7b1e418ef4..f76592d7fd 100644 --- a/tests/expectations/compiler/compiler/function/duplicate_definition_fail.leo.out +++ b/tests/expectations/compiler/compiler/function/duplicate_definition_fail.leo.out @@ -2,4 +2,4 @@ namespace: Compile expectation: Fail outputs: - - " --> compiler-test:6:12\n |\n 6 | return 10u32; \n | ^^^^^\n |\n = unexpected type, expected: '()', received: 'u32'" + - " --> compiler-test:8:1\n |\n 8 | function main() {\n|\n 9 | ...\n|\n 10 | }\n | ^\n |\n = a function named \"main\" already exists in this scope" diff --git a/tests/expectations/compiler/compiler/function/multiple_returns_fail.leo.out b/tests/expectations/compiler/compiler/function/multiple_returns_fail.leo.out index 5fcaab60f3..6738b2788e 100644 --- a/tests/expectations/compiler/compiler/function/multiple_returns_fail.leo.out +++ b/tests/expectations/compiler/compiler/function/multiple_returns_fail.leo.out @@ -2,4 +2,4 @@ namespace: Compile expectation: Fail outputs: - - " --> compiler-test:4:5\n |\n 4 | if true {\n 5 | ...\n 6 | }\n | ^\n |\n = function 'main' failed to validate return path: 'cannot have asymmetrical return in if statement'" + - " --> compiler-test:4:5\n |\n 4 | if true {\n|\n 5 | ...\n|\n 6 | }\n | ^\n |\n = function 'main' failed to validate return path: 'cannot have asymmetrical return in if statement'" diff --git a/tests/expectations/compiler/compiler/function/multiple_returns_fail_conditional.leo.out b/tests/expectations/compiler/compiler/function/multiple_returns_fail_conditional.leo.out index 52b50d8a3e..ee103c4030 100644 --- a/tests/expectations/compiler/compiler/function/multiple_returns_fail_conditional.leo.out +++ b/tests/expectations/compiler/compiler/function/multiple_returns_fail_conditional.leo.out @@ -2,4 +2,4 @@ namespace: Compile expectation: Fail outputs: - - " --> compiler-test:3:1\n |\n 3 | function main() -> bool {\n 4 | ...\n 5 | }\n 6 | \n 7 | \n 8 | \n 9 | \n 10 | \n | ^\n |\n = function 'main' missing return for all paths" + - " --> compiler-test:3:1\n |\n 3 | function main() -> bool {\n|\n 4 | ...\n|\n 5 | }\n|\n 6 | \n|\n 7 | \n|\n 8 | \n|\n 9 | \n|\n 10 | \n | ^\n |\n = function 'main' missing return for all paths" diff --git a/tests/expectations/compiler/compiler/input_files/program_registers/registers_fail.leo.out b/tests/expectations/compiler/compiler/input_files/program_registers/registers_fail.leo.out index e074c91490..6609ce03a3 100644 --- a/tests/expectations/compiler/compiler/input_files/program_registers/registers_fail.leo.out +++ b/tests/expectations/compiler/compiler/input_files/program_registers/registers_fail.leo.out @@ -2,4 +2,4 @@ namespace: Compile expectation: Fail outputs: - - " --> compiler-test:3:1\n |\n 3 | function main() -> bool {\n 4 | ...\n 5 | }\n | ^\n |\n = Mismatched types. Expected register output type `u8`, found type `bool`." + - " --> compiler-test:3:1\n |\n 3 | function main() -> bool {\n|\n 4 | ...\n|\n 5 | }\n | ^\n |\n = Mismatched types. Expected register output type `u8`, found type `bool`." diff --git a/tests/expectations/parser/parser/statement/console.leo.out b/tests/expectations/parser/parser/statement/console.leo.out index 2ed38532c9..4ff3e93b83 100644 --- a/tests/expectations/parser/parser/statement/console.leo.out +++ b/tests/expectations/parser/parser/statement/console.leo.out @@ -80,73 +80,6 @@ outputs: col_stop: 18 path: test content: "console.error(\"x\");" - - Console: - function: - Debug: - string: - - Scalar: 123 - - Scalar: 125 - parameters: - - Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":21,\\\"col_stop\\\":22,\\\"path\\\":\\\"test\\\",\\\"content\\\":\\\"console.debug(\\\\\\\"{}\\\\\\\", x);\\\"}\"}" - span: - line_start: 1 - line_stop: 1 - col_start: 15 - col_stop: 22 - path: test - content: "console.debug(\"{}\", x);" - span: - line_start: 1 - line_stop: 1 - col_start: 1 - col_stop: 22 - path: test - content: "console.debug(\"{}\", x);" - - Console: - function: - Debug: - string: - - Scalar: 123 - - Scalar: 125 - - Scalar: 123 - - Scalar: 125 - parameters: - - Identifier: "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":23,\\\"col_stop\\\":24,\\\"path\\\":\\\"test\\\",\\\"content\\\":\\\"console.debug(\\\\\\\"{}{}\\\\\\\", x, y);\\\"}\"}" - - Identifier: "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":26,\\\"col_stop\\\":27,\\\"path\\\":\\\"test\\\",\\\"content\\\":\\\"console.debug(\\\\\\\"{}{}\\\\\\\", x, y);\\\"}\"}" - span: - line_start: 1 - line_stop: 1 - col_start: 15 - col_stop: 27 - path: test - content: "console.debug(\"{}{}\", x, y);" - span: - line_start: 1 - line_stop: 1 - col_start: 1 - col_stop: 27 - path: test - content: "console.debug(\"{}{}\", x, y);" - - Console: - function: - Debug: - string: - - Scalar: 120 - parameters: [] - span: - line_start: 1 - line_stop: 1 - col_start: 15 - col_stop: 18 - path: test - content: "console.debug(\"x\");" - span: - line_start: 1 - line_stop: 1 - col_start: 1 - col_stop: 18 - path: test - content: "console.debug(\"x\");" - Console: function: Log: diff --git a/tests/parser/statement/console.leo b/tests/parser/statement/console.leo index ba1b5e2cf4..773ec668b0 100644 --- a/tests/parser/statement/console.leo +++ b/tests/parser/statement/console.leo @@ -13,13 +13,6 @@ console.error("{}{}", x, y); console.error("x"); -console.debug("{}", x); - -console.debug("{}{}", x, y); - -console.debug("x"); - - console.log("{}", x); console.log("{}{}", x, y);