Merge branch 'master' of https://github.com/AleoHQ/leo into feature/update_command

This commit is contained in:
howardwu 2020-08-19 01:43:53 -07:00
commit 3a233add99
389 changed files with 1410 additions and 1549 deletions

133
README.md
View File

@ -1,7 +1,10 @@
# The Leo Programming Language
<h1 align="center">The Leo Programming Language</h1>
![CI](https://github.com/AleoHQ/leo/workflows/CI/badge.svg)
[![codecov](https://codecov.io/gh/AleoHQ/leo/branch/master/graph/badge.svg?token=S6MWO60SYL)](https://codecov.io/gh/AleoHQ/leo)
<p align="center">
<a href="https://github.com/AleoHQ/leo/actions"><img src="https://github.com/AleoHQ/leo/workflows/CI/badge.svg"></a>
<a href="https://codecov.io/gh/AleoHQ/leo"><img src="https://codecov.io/gh/AleoHQ/leo/branch/master/graph/badge.svg?token=S6MWO60SYL"/></a>
<a href="https://discord.gg/TTexWvt"><img src="https://img.shields.io/discord/700454073459015690?logo=discord"/></a>
</p>
Leo is a functional, statically-typed programming language built for writing private applications.
@ -13,12 +16,7 @@ Leo is a functional, statically-typed programming language built for writing pri
* [2.2a Build from Crates.io](#22a-build-from-cratesio)
* [2.2b Build from Source Code](#22b-build-from-source-code)
* [3. Quick Start](#3-quick-start)
* [4. Flying Tour](#4-flying-tour)
* [4.1 Functions](#41-functions)
* [4.2 Testing](#42-testing)
* [4.3 Data Types](#43-data-types)
* [4.4 Circuits](#44-circuits)
* [4.5 Imports](#45-imports)
* [4. Documentation](#4-documentation)
* [5. Contributing](#5-contributing)
* [6. License](#6-license)
@ -26,10 +24,15 @@ Leo is a functional, statically-typed programming language built for writing pri
## 1. Overview
Welcome to the Leo programming language.
Leo exists to provide a simple high-level language that compiles to a rank one constraint system (R1CS) circuit.
With Leo, you can write circuits to support zero-knowledge tokens, private stable coins, and decentralized marketplaces.
Leo provides a high-level language that abstracts low-level cryptographic concepts and makes it easy to
integrate private applications into your stack. Leo compiles to circuits making zero-knowledge proofs practical.
The syntax of Leo is influenced by JavaScript, Python, Scala, and Rust with a strong emphasis on readability and ease-of-use.
The syntax of Leo is influenced by traditional programming languages like JavaScript, Scala, and Rust, with a strong emphasis on readability and ease-of-use.
Leo offers developers with tools to sanity check circuits including unit tests, integration tests, and console functions.
Leo is one part of a greater ecosystem for building private applications on [Aleo](https://aleo.org/). If your goal is to build a user experience
on the web that is both truly personal and truly private, then we recommend downloading the [Aleo Studio IDE](https://aleo.studio/)
and checking out the [Aleo Package Manager]().
## 2. Build Guide
@ -100,105 +103,12 @@ The `leo run` command will compile the main program, generate keys for a trusted
Congratulations! You've just run your first Leo program.
## 4. Flying Tour
## 4. Documentation
The best way to get to know Leo is by writing some code. We will fly through a high level overview of a Leo file.
To gain a deeper understanding of the Leo language, then check out the [developer documentation](https://developer.aleo.org/developer/getting_started/overview)
**Square Root Example**: Let's prove that we know the square root of a number.
**`src/main.leo`**
```rust // change this to leo
function main(a: u32, b: u32) -> bool {
return square_root(a, b)
}
function square_root(a: u32, b: u32) -> bool {
return a * a == b
}
test function test_square_root() {
let a: u32 = 5;
let b: u32 = 25;
let result = square_root(a, b);
console.assert(result == true);
}
```
### 4.1 Functions
The `main` function is the entrypoint of a Leo program.
`leo run` will provide private inputs directly to the function for proving and store the program result in an output file.
The `square_root` function is called by `main` with private inputs `a` and `b` which are both unsigned `u32` integers.
### 4.2 Testing
A naive way to test `square_root` would be to execute `leo run` several times on different inputs and check the output of the program each time.
Luckily, we can write unit tests in Leo using the `test function` syntax.
In `test_square_root` we can sanity check our code without having to load in private inputs from a file every time.
Want to upgrade your test function into an integration test?
In Leo you can add a test context annotation that loads different sets of private inputs to make your test suite even more robust.
The last line of `test_square_root` uses the console function `console.assert`.
This function along with `console.log`, `console.debug`, and `console.error` provide developers with tools that are run without
affecting the underlying constraint system.
### 4.3 Data Types
Leo supports boolean, unsigned integer, signed integer, field, group element, and address data types.
Collections of data types can be created in the form of static arrays and tuples.
### 4.4 Circuits
**Circuits Example**
**`src/main.leo`**
```rust
circuit Point {
x: u32,
y: u32,
static function new() -> Self {
return Self {
x: 0,
y: 0,
}
}
function add() -> u32 {
return self.x + self.y
}
}
function main() {
let mut p = Point::new();
p.x = 4u32;
p.y = 6u32;
let sum = p.add();
console.log("The sum is {}", sum);
}
```
Circuits in leo are similar to structures in other object-oriented languages.
They provide a composite data type that can store primitive values and provide functions for instantiation and computation.
The `static` keyword modifies the `new` function so it can be called without instantiating the circuit.
Leo introduces `Self` and `self` keywords to access circuit member values.
### 4.5 Imports
Imports fetch other circuits and functions and bring them into the current file scope.
Leo supports imports for dependencies that are declared locally or in an imported package.
Importing packages can be accomplished using the `leo add` command in the CLI.
* [Hello World - Next Steps](https://developer.aleo.org/developer/getting_started/hello_world)
* [Leo Language Documentation](https://developer.aleo.org/developer/language/layout)
* [Leo CLI Documentation](https://developer.aleo.org/developer/cli/new)
* [Homepage](https://developer.aleo.org/developer/getting_started/overview)
## 5. Contributing
@ -206,6 +116,5 @@ Please see our guidelines in the [developer documentation](https://developer.ale
Thank you for helping make Leo better!
## 6. License
[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](./LICENSE.md)
[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](./LICENSE.md)

View File

@ -0,0 +1,21 @@
use crate::{ast::Rule, expressions::Expression, SpanDef};
use pest::Span;
use pest_ast::FromPest;
use serde::Serialize;
use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
#[pest_ast(rule(Rule::console_assert))]
pub struct ConsoleAssert<'ast> {
pub expression: Expression<'ast>,
#[pest_ast(outer())]
#[serde(with = "SpanDef")]
pub span: Span<'ast>,
}
impl<'ast> fmt::Display for ConsoleAssert<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "assert({})", self.expression)
}
}

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::{ast::Rule, SpanDef};
use crate::{ast::Rule, console::FormattedString, SpanDef};
use pest::Span;
use pest_ast::FromPest;
@ -22,15 +22,16 @@ use serde::Serialize;
use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
#[pest_ast(rule(Rule::error))]
pub struct Error<'ast> {
#[pest_ast(rule(Rule::console_debug))]
pub struct ConsoleDebug<'ast> {
pub string: FormattedString<'ast>,
#[pest_ast(outer())]
#[serde(with = "SpanDef")]
pub span: Span<'ast>,
}
impl<'ast> fmt::Display for Error<'ast> {
impl<'ast> fmt::Display for ConsoleDebug<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "error")
write!(f, "debug({})", self.string)
}
}

View File

@ -0,0 +1,21 @@
use crate::{ast::Rule, console::FormattedString, SpanDef};
use pest::Span;
use pest_ast::FromPest;
use serde::Serialize;
use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
#[pest_ast(rule(Rule::console_error))]
pub struct ConsoleError<'ast> {
pub string: FormattedString<'ast>,
#[pest_ast(outer())]
#[serde(with = "SpanDef")]
pub span: Span<'ast>,
}
impl<'ast> fmt::Display for ConsoleError<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "error({})", self.string)
}
}

View File

@ -0,0 +1,28 @@
use crate::{
ast::Rule,
console::{ConsoleAssert, ConsoleDebug, ConsoleError, ConsoleLog},
};
use pest_ast::FromPest;
use serde::Serialize;
use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
#[pest_ast(rule(Rule::console_function))]
pub enum ConsoleFunction<'ast> {
Assert(ConsoleAssert<'ast>),
Debug(ConsoleDebug<'ast>),
Error(ConsoleError<'ast>),
Log(ConsoleLog<'ast>),
}
impl<'ast> fmt::Display for ConsoleFunction<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
ConsoleFunction::Assert(assert) => write!(f, "{}", assert),
ConsoleFunction::Debug(debug) => write!(f, "{}", debug),
ConsoleFunction::Error(error) => write!(f, "{}", error),
ConsoleFunction::Log(log) => write!(f, "{}", log),
}
}
}

View File

@ -0,0 +1,28 @@
use crate::{
ast::Rule,
common::LineEnd,
console::{ConsoleFunction, ConsoleKeyword},
SpanDef,
};
use pest::Span;
use pest_ast::FromPest;
use serde::Serialize;
use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
#[pest_ast(rule(Rule::console_function_call))]
pub struct ConsoleFunctionCall<'ast> {
pub keyword: ConsoleKeyword<'ast>,
pub function: ConsoleFunction<'ast>,
pub line_end: LineEnd,
#[pest_ast(outer())]
#[serde(with = "SpanDef")]
pub span: Span<'ast>,
}
impl<'ast> fmt::Display for ConsoleFunctionCall<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "console.{};", self.function)
}
}

View File

@ -19,18 +19,11 @@ use crate::{ast::Rule, SpanDef};
use pest::Span;
use pest_ast::FromPest;
use serde::Serialize;
use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
#[pest_ast(rule(Rule::print))]
pub struct Print<'ast> {
#[pest_ast(rule(Rule::console_keyword))]
pub struct ConsoleKeyword<'ast> {
#[pest_ast(outer())]
#[serde(with = "SpanDef")]
pub span: Span<'ast>,
}
impl<'ast> fmt::Display for Print<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "print")
}
}

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::{ast::Rule, SpanDef};
use crate::{ast::Rule, console::FormattedString, SpanDef};
use pest::Span;
use pest_ast::FromPest;
@ -22,15 +22,16 @@ use serde::Serialize;
use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
#[pest_ast(rule(Rule::debug))]
pub struct Debug<'ast> {
#[pest_ast(rule(Rule::console_log))]
pub struct ConsoleLog<'ast> {
pub string: FormattedString<'ast>,
#[pest_ast(outer())]
#[serde(with = "SpanDef")]
pub span: Span<'ast>,
}
impl<'ast> fmt::Display for Debug<'ast> {
impl<'ast> fmt::Display for ConsoleLog<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "debug")
write!(f, "log({})", self.string)
}
}

View File

@ -16,7 +16,7 @@
use crate::{
ast::{span_into_string, Rule},
macros::{FormattedContainer, FormattedParameter},
console::{FormattedContainer, FormattedParameter},
SpanDef,
};

29
ast/src/console/mod.rs Normal file
View File

@ -0,0 +1,29 @@
pub mod console_assert;
pub use console_assert::*;
pub mod console_debug;
pub use console_debug::*;
pub mod console_error;
pub use console_error::*;
pub mod console_function;
pub use console_function::*;
pub mod console_function_call;
pub use console_function_call::*;
pub mod console_keyword;
pub use console_keyword::*;
pub mod console_log;
pub use console_log::*;
pub mod formatted_container;
pub use formatted_container::*;
pub mod formatted_parameter;
pub use formatted_parameter::*;
pub mod formatted_string;
pub use formatted_string::*;

View File

@ -25,6 +25,7 @@ protected_name = {
| "as"
| "circuit"
| "const"
| "console"
| "else"
| "false"
| "field"
@ -234,7 +235,8 @@ value_boolean = { "true" | "false" }
value_field = ${ value_number ~ type_field }
// Declared in values/group_value.rs
value_group = ${ group_tuple ~ type_group }
value_group = ${ group_single_or_tuple ~ type_group }
group_single_or_tuple = {value_number | group_tuple}
group_tuple = !{"(" ~ group_coordinate ~ "," ~ group_coordinate ~ ")"}
// Declared in values/group_coordinate.rs
@ -345,18 +347,13 @@ statement = {
(statement_return
| statement_conditional
| statement_for
| statement_macro
| console_function_call
| statement_definition
| statement_assign
| statement_expression
) ~ NEWLINE*
}
// Declared in statements/macro_statement.rs
statement_macro = {
assert_eq
| formatted_macro
}
// Declared in statements/assign_statement.rs
statement_assign = { assignee ~ operation_assign ~ expression ~ LINE_END }
@ -431,15 +428,35 @@ import_symbol = { identifier ~ ("as " ~ identifier)? }
COMMENT = _{ ("/*" ~ (!"*/" ~ ANY)* ~ "*/") | ("//" ~ (!NEWLINE ~ ANY)*) }
WHITESPACE = _{ " " | "\t" ~ (NEWLINE)* } // pest implicit whitespace keyword
/// Macros
/// Console Functions
// Declared in macros/assert_eq.rs
assert_eq = {"assert_eq!" ~ "(" ~ NEWLINE* ~ expression ~ "," ~ NEWLINE* ~ expression ~ NEWLINE* ~ ")" ~ LINE_END}
// Declared in console/console_function_call.rs
console_function_call = ${console_keyword ~ "." ~ console_function ~ LINE_END}
// Declared in macros/formatted_macro.rs
formatted_macro = { macro_name ~ macro_symbol ~ "(" ~ formatted_string? ~ ")" ~ LINE_END}
// Declared in console/console_keyword.rs
console_keyword = {"console"}
// Declared in macros/formatted_string.rs
// Declared in console/console_function.rs
console_function = {
console_assert
| console_debug
| console_error
| console_log
}
// Declared in console/console_assert.rs
console_assert = !{"assert(" ~ expression ~ ")"}
// Declared in console/console_debug.rs
console_debug = !{"debug(" ~ formatted_string? ~ ")"}
// Declared in console/console_error.rs
console_error = !{"error(" ~ formatted_string? ~ ")"}
// Declared in console/console_log.rs
console_log = !{"log(" ~ formatted_string? ~ ")"}
// Declared in console/formatted_string.rs
formatted_string = {
"\""
~ (!"\"" ~ (formatted_container | ANY))*
@ -447,31 +464,12 @@ formatted_string = {
~ ("," ~ formatted_parameter)*
}
// Declared in macros/formatted_container.rs
// Declared in console/formatted_container.rs
formatted_container = { "{" ~ "}"}
// Declared in macros/formatted_parameter.rs
// Declared in console/formatted_parameter.rs
formatted_parameter = { expression }
// Declared in macros/macro_symbol.rs
macro_symbol = {"!"}
// Declared in macros/macro_name.rs
macro_name = {
debug
| error
| print
}
// Declared in macros/print.rs
print = {"print"}
// Declared in macros/debug.rs
debug = {"debug"}
// Declared in macros/error.rs
error = {"error"}
/// Annotations
// Declared in annotations/annotation.rs

View File

@ -27,12 +27,12 @@ pub mod access;
pub mod annotations;
pub mod circuits;
pub mod common;
pub mod console;
pub mod definitions;
pub mod expressions;
pub mod files;
pub mod functions;
pub mod imports;
pub mod macros;
pub mod operations;
pub mod statements;
pub mod types;

View File

@ -1,39 +0,0 @@
// Copyright (C) 2019-2020 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{ast::Rule, common::LineEnd, expressions::Expression, SpanDef};
use pest::Span;
use pest_ast::FromPest;
use serde::Serialize;
use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
#[pest_ast(rule(Rule::assert_eq))]
pub struct AssertEq<'ast> {
pub left: Expression<'ast>,
pub right: Expression<'ast>,
pub line_end: LineEnd,
#[pest_ast(outer())]
#[serde(with = "SpanDef")]
pub span: Span<'ast>,
}
impl<'ast> fmt::Display for AssertEq<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "assert_eq({}, {});", self.left, self.right)
}
}

View File

@ -1,52 +0,0 @@
// Copyright (C) 2019-2020 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{
ast::Rule,
common::LineEnd,
macros::{FormattedString, MacroName, MacroSymbol},
SpanDef,
};
use pest::Span;
use pest_ast::FromPest;
use serde::Serialize;
use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
#[pest_ast(rule(Rule::formatted_macro))]
pub struct FormattedMacro<'ast> {
pub name: MacroName<'ast>,
pub symbol: MacroSymbol,
pub string: Option<FormattedString<'ast>>,
pub line_end: LineEnd,
#[pest_ast(outer())]
#[serde(with = "SpanDef")]
pub span: Span<'ast>,
}
impl<'ast> fmt::Display for FormattedMacro<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"{}{}({}){}",
self.name,
self.symbol,
self.string.as_ref().map(|s| s.to_string()).unwrap_or("".to_string()),
self.line_end
)
}
}

View File

@ -1,42 +0,0 @@
// Copyright (C) 2019-2020 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{
ast::Rule,
macros::{Debug, Error, Print},
};
use pest_ast::FromPest;
use serde::Serialize;
use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
#[pest_ast(rule(Rule::macro_name))]
pub enum MacroName<'ast> {
Debug(Debug<'ast>),
Error(Error<'ast>),
Print(Print<'ast>),
}
impl<'ast> fmt::Display for MacroName<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
MacroName::Debug(ref debug) => write!(f, "{}", debug),
MacroName::Error(ref error) => write!(f, "{}", error),
MacroName::Print(ref print_line) => write!(f, "{}", print_line),
}
}
}

View File

@ -1,31 +0,0 @@
// Copyright (C) 2019-2020 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::ast::Rule;
use pest_ast::FromPest;
use serde::Serialize;
use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
#[pest_ast(rule(Rule::macro_symbol))]
pub struct MacroSymbol {}
impl fmt::Display for MacroSymbol {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "!")
}
}

View File

@ -1,45 +0,0 @@
// Copyright (C) 2019-2020 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// 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/>.
pub mod assert_eq;
pub use assert_eq::*;
pub mod debug;
pub use debug::*;
pub mod error;
pub use error::*;
pub mod formatted_container;
pub use formatted_container::*;
pub mod formatted_parameter;
pub use formatted_parameter::*;
pub mod formatted_string;
pub use formatted_string::*;
pub mod formatted_macro;
pub use formatted_macro::*;
pub mod macro_name;
pub use macro_name::*;
pub mod macro_symbol;
pub use macro_symbol::*;
pub mod print;
pub use print::*;

View File

@ -1,40 +0,0 @@
// Copyright (C) 2019-2020 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{
ast::Rule,
macros::{AssertEq, FormattedMacro},
};
use pest_ast::FromPest;
use serde::Serialize;
use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
#[pest_ast(rule(Rule::statement_macro))]
pub enum MacroStatement<'ast> {
AssertEq(AssertEq<'ast>),
Formatted(FormattedMacro<'ast>),
}
impl<'ast> fmt::Display for MacroStatement<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
MacroStatement::AssertEq(ref assert) => write!(f, "{}", assert),
MacroStatement::Formatted(ref formatted) => write!(f, "{}", formatted),
}
}
}

View File

@ -14,9 +14,6 @@
// 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/>.
pub mod macro_statement;
pub use macro_statement::*;
pub mod assign_statement;
pub use assign_statement::*;

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::{ast::Rule, statements::*};
use crate::{ast::Rule, console::ConsoleFunctionCall, statements::*};
use pest_ast::FromPest;
use serde::Serialize;
@ -28,7 +28,7 @@ pub enum Statement<'ast> {
Assign(AssignStatement<'ast>),
Conditional(ConditionalStatement<'ast>),
Iteration(ForStatement<'ast>),
Assert(MacroStatement<'ast>),
Console(ConsoleFunctionCall<'ast>),
Expression(ExpressionStatement<'ast>),
}
@ -40,7 +40,7 @@ impl<'ast> fmt::Display for Statement<'ast> {
Statement::Assign(ref statement) => write!(f, "{}", statement),
Statement::Conditional(ref statement) => write!(f, "{}", statement),
Statement::Iteration(ref statement) => write!(f, "{}", statement),
Statement::Assert(ref statement) => write!(f, "{}", statement),
Statement::Console(ref statement) => write!(f, "{}", statement),
Statement::Expression(ref statement) => write!(f, "{}", statement.expression),
}
}

View File

@ -14,7 +14,12 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{ast::Rule, types::GroupType, values::GroupCoordinate, SpanDef};
use crate::{
ast::Rule,
types::GroupType,
values::{GroupCoordinate, NumberValue},
SpanDef,
};
use pest::Span;
use pest_ast::FromPest;
@ -24,7 +29,7 @@ use std::fmt;
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
#[pest_ast(rule(Rule::value_group))]
pub struct GroupValue<'ast> {
pub value: GroupTuple<'ast>,
pub value: GroupRepresentation<'ast>,
pub type_: GroupType,
#[pest_ast(outer())]
#[serde(with = "SpanDef")]
@ -37,6 +42,22 @@ impl<'ast> fmt::Display for GroupValue<'ast> {
}
}
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
#[pest_ast(rule(Rule::group_single_or_tuple))]
pub enum GroupRepresentation<'ast> {
Single(NumberValue<'ast>),
Tuple(GroupTuple<'ast>),
}
impl<'ast> fmt::Display for GroupRepresentation<'ast> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
GroupRepresentation::Single(number) => write!(f, "{}", number),
GroupRepresentation::Tuple(tuple) => write!(f, "{}", tuple),
}
}
}
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
#[pest_ast(rule(Rule::group_tuple))]
pub struct GroupTuple<'ast> {

View File

@ -0,0 +1,50 @@
//! Enforces an assert equals statement in a compiled Leo program.
use crate::{errors::ConsoleError, program::ConstrainedProgram, value::ConstrainedValue, GroupType};
use leo_typed::{Expression, Span, Type};
use snarkos_models::{
curves::{Field, PrimeField},
gadgets::{r1cs::ConstraintSystem, utilities::boolean::Boolean},
};
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
pub fn evaluate_console_assert<CS: ConstraintSystem<F>>(
&mut self,
cs: &mut CS,
file_scope: String,
function_scope: String,
indicator: Option<Boolean>,
expression: Expression,
span: Span,
) -> Result<(), ConsoleError> {
let expected_type = Some(Type::Boolean);
let expression_string = expression.to_string();
// Evaluate assert expression
let assert_expression = self.enforce_expression(cs, file_scope, function_scope, expected_type, expression)?;
// If the indicator bit is false, do not evaluate the assertion
// This is okay since we are not enforcing any constraints
let false_boolean = Boolean::Constant(false);
if let Some(indicator_bool) = indicator {
if indicator_bool.eq(&false_boolean) {
return Ok(()); // continue execution
}
}
// Unwrap assertion value and handle errors
let result_option = match assert_expression {
ConstrainedValue::Boolean(boolean) => boolean.get_value(),
_ => return Err(ConsoleError::assertion_must_be_boolean(expression_string, span.clone())),
};
let result_bool = result_option.ok_or(ConsoleError::assertion_depends_on_input(span.clone()))?;
if !result_bool {
return Err(ConsoleError::assertion_failed(expression_string, span));
}
Ok(())
}
}

View File

@ -0,0 +1,62 @@
//! Evaluates a macro in a compiled Leo program.
use crate::{errors::ConsoleError, program::ConstrainedProgram, GroupType};
use leo_typed::{ConsoleFunction, ConsoleFunctionCall};
use snarkos_models::{
curves::{Field, PrimeField},
gadgets::{r1cs::ConstraintSystem, utilities::boolean::Boolean},
};
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
pub fn evaluate_console_function_call<CS: ConstraintSystem<F>>(
&mut self,
cs: &mut CS,
file_scope: String,
function_scope: String,
indicator: Option<Boolean>,
console: ConsoleFunctionCall,
) -> Result<(), ConsoleError> {
match console.function {
ConsoleFunction::Assert(expression) => {
self.evaluate_console_assert(cs, file_scope, function_scope, indicator, expression, console.span)?;
}
ConsoleFunction::Debug(string) => {
let string = self.format(cs, file_scope, function_scope, string)?;
if unwrap_indicator_value(indicator) {
log::debug!("{}", string);
}
}
ConsoleFunction::Error(string) => {
let string = self.format(cs, file_scope, function_scope, string)?;
if unwrap_indicator_value(indicator) {
log::error!("{}", string);
}
}
ConsoleFunction::Log(string) => {
let string = self.format(cs, file_scope, function_scope, string)?;
if unwrap_indicator_value(indicator) {
log::info!("{}", string);
}
}
}
Ok(())
}
}
// Return the indicator boolean gadget value or true if it is None
// This is okay since we are not enforcing any constraints
fn unwrap_indicator_value(indicator: Option<Boolean>) -> bool {
let false_boolean = Boolean::constant(false);
if let Some(indicator_bool) = indicator {
if indicator_bool.eq(&false_boolean) {
return false;
}
}
true
}

View File

@ -16,7 +16,7 @@
//! Evaluates a formatted string in a compiled Leo program.
use crate::{errors::MacroError, program::ConstrainedProgram, GroupType};
use crate::{errors::ConsoleError, program::ConstrainedProgram, GroupType};
use leo_typed::FormattedString;
use snarkos_models::{
@ -31,10 +31,10 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
file_scope: String,
function_scope: String,
formatted: FormattedString,
) -> Result<String, MacroError> {
) -> Result<String, ConsoleError> {
// Check that containers and parameters match
if formatted.containers.len() != formatted.parameters.len() {
return Err(MacroError::length(
return Err(ConsoleError::length(
formatted.containers.len(),
formatted.parameters.len(),
formatted.span.clone(),

View File

@ -0,0 +1,8 @@
pub mod assert;
pub use assert::*;
pub mod console;
pub use self::console::*;
pub mod format;
pub use self::format::*;

View File

@ -0,0 +1,53 @@
use crate::errors::ExpressionError;
use leo_typed::{Error as FormattedError, Span};
use std::path::PathBuf;
#[derive(Debug, Error)]
pub enum ConsoleError {
#[error("{}", _0)]
Error(#[from] FormattedError),
#[error("{}", _0)]
Expression(#[from] ExpressionError),
}
impl ConsoleError {
pub fn set_path(&mut self, path: PathBuf) {
match self {
ConsoleError::Expression(error) => error.set_path(path),
ConsoleError::Error(error) => error.set_path(path),
}
}
fn new_from_span(message: String, span: Span) -> Self {
ConsoleError::Error(FormattedError::new_from_span(message, span))
}
pub fn length(containers: usize, parameters: usize, span: Span) -> Self {
let message = format!(
"Formatter given {} containers and found {} parameters",
containers, parameters
);
Self::new_from_span(message, span)
}
pub fn assertion_depends_on_input(span: Span) -> Self {
let message = format!("console.assert() failed to evaluate. This error is caused by empty input file values");
Self::new_from_span(message, span)
}
pub fn assertion_failed(expression: String, span: Span) -> Self {
let message = format!("Assertion `{}` failed", expression);
Self::new_from_span(message, span)
}
pub fn assertion_must_be_boolean(expression: String, span: Span) -> Self {
let message = format!("Assertion expression `{}` must evaluate to a boolean value", expression);
Self::new_from_span(message, span)
}
}

View File

@ -67,13 +67,19 @@ impl ExpressionError {
pub fn cannot_enforce(operation: String, error: SynthesisError, span: Span) -> Self {
let message = format!(
"the gadget operation `{}` failed due to synthesis error `{}`",
"the gadget operation `{}` failed due to synthesis error `{:?}`",
operation, error,
);
Self::new_from_span(message, span)
}
pub fn cannot_evaluate(operation: String, span: Span) -> Self {
let message = format!("Mismatched types found for operation `{}`", operation);
Self::new_from_span(message, span)
}
pub fn conditional_boolean(actual: String, span: Span) -> Self {
let message = format!("if, else conditional must resolve to a boolean, found `{}`", actual);

View File

@ -1,51 +0,0 @@
// Copyright (C) 2019-2020 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// 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::ExpressionError;
use leo_typed::{Error as FormattedError, Span};
use std::path::PathBuf;
#[derive(Debug, Error)]
pub enum MacroError {
#[error("{}", _0)]
Error(#[from] FormattedError),
#[error("{}", _0)]
Expression(#[from] ExpressionError),
}
impl MacroError {
pub fn set_path(&mut self, path: PathBuf) {
match self {
MacroError::Expression(error) => error.set_path(path),
MacroError::Error(error) => error.set_path(path),
}
}
fn new_from_span(message: String, span: Span) -> Self {
MacroError::Error(FormattedError::new_from_span(message, span))
}
pub fn length(containers: usize, parameters: usize, span: Span) -> Self {
let message = format!(
"Formatter given {} containers and found {} parameters",
containers, parameters
);
Self::new_from_span(message, span)
}
}

View File

@ -26,8 +26,8 @@ pub use self::function::*;
pub mod import;
pub use self::import::*;
pub mod macro_;
pub use self::macro_::*;
pub mod console;
pub use self::console::*;
pub mod output_file;
pub use self::output_file::*;

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, BooleanError, ExpressionError, IntegerError, MacroError, ValueError};
use crate::errors::{AddressError, BooleanError, ConsoleError, ExpressionError, IntegerError, ValueError};
use leo_typed::{Error as FormattedError, Span, Type};
use std::path::PathBuf;
@ -37,7 +37,7 @@ pub enum StatementError {
IntegerError(#[from] IntegerError),
#[error("{}", _0)]
MacroError(#[from] MacroError),
MacroError(#[from] ConsoleError),
#[error("{}", _0)]
ValueError(#[from] ValueError),
@ -78,12 +78,6 @@ impl StatementError {
Self::new_from_span(message, span)
}
pub fn assertion_failed(left: String, right: String, span: Span) -> Self {
let message = format!("Assertion `{} == {}` failed", left, right);
Self::new_from_span(message, span)
}
pub fn conditional_boolean(actual: String, span: Span) -> Self {
let message = format!("If, else conditional must resolve to a boolean, found `{}`", actual);

View File

@ -44,7 +44,7 @@ impl AddressError {
pub fn cannot_enforce(operation: String, error: SynthesisError, span: Span) -> Self {
let message = format!(
"the address operation `{}` failed due to the synthesis error `{}`",
"the address operation `{:?}` failed due to the synthesis error `{}`",
operation, error,
);

View File

@ -38,7 +38,7 @@ impl BooleanError {
pub fn cannot_enforce(operation: String, error: SynthesisError, span: Span) -> Self {
let message = format!(
"the boolean operation `{}` failed due to the synthesis error `{}`",
"the boolean operation `{}` failed due to the synthesis error `{:?}`",
operation, error,
);

View File

@ -37,14 +37,14 @@ impl FieldError {
}
pub fn negate_operation(error: SynthesisError, span: Span) -> Self {
let message = format!("field negation failed due to synthesis error `{}`", error,);
let message = format!("field negation failed due to synthesis error `{:?}`", error,);
Self::new_from_span(message, span)
}
pub fn binary_operation(operation: String, error: SynthesisError, span: Span) -> Self {
let message = format!(
"the field binary operation `{}` failed due to synthesis error `{}`",
"the field binary operation `{}` failed due to synthesis error `{:?}`",
operation, error,
);
@ -70,7 +70,7 @@ impl FieldError {
}
pub fn synthesis_error(error: SynthesisError, span: Span) -> Self {
let message = format!("compilation failed due to field synthesis error `{}`", error);
let message = format!("compilation failed due to field synthesis error `{:?}`", error);
Self::new_from_span(message, span)
}

View File

@ -37,14 +37,14 @@ impl GroupError {
}
pub fn negate_operation(error: SynthesisError, span: Span) -> Self {
let message = format!("group negation failed due to the synthesis error `{}`", error,);
let message = format!("group negation failed due to the synthesis error `{:?}`", error,);
Self::new_from_span(message, span)
}
pub fn binary_operation(operation: String, error: SynthesisError, span: Span) -> Self {
let message = format!(
"the group binary operation `{}` failed due to the synthesis error `{}`",
"the group binary operation `{}` failed due to the synthesis error `{:?}`",
operation, error,
);
@ -64,7 +64,7 @@ impl GroupError {
}
pub fn synthesis_error(error: SynthesisError, span: Span) -> Self {
let message = format!("compilation failed due to group synthesis error `{}`", error);
let message = format!("compilation failed due to group synthesis error `{:?}`", error);
Self::new_from_span(message, span)
}

View File

@ -39,7 +39,7 @@ impl IntegerError {
pub fn cannot_enforce(operation: String, error: SynthesisError, span: Span) -> Self {
let message = format!(
"the integer operation `{}` failed due to the synthesis error `{}`",
"the integer operation `{}` failed due to the synthesis error `{:?}`",
operation, error,
);

View File

@ -54,7 +54,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
Expression::Address(address, span) => Ok(ConstrainedValue::Address(Address::new(address, span)?)),
Expression::Boolean(boolean, span) => Ok(ConstrainedValue::Boolean(new_bool_constant(boolean, span)?)),
Expression::Field(field, span) => Ok(ConstrainedValue::Field(FieldType::constant(field, span)?)),
Expression::Group(group_affine) => Ok(ConstrainedValue::Group(G::constant(group_affine)?)),
Expression::Group(group_element) => Ok(ConstrainedValue::Group(G::constant(group_element)?)),
Expression::Implicit(value, span) => Ok(enforce_number_implicit(expected_type, value, span)?),
Expression::Integer(type_, integer, span) => {
Ok(ConstrainedValue::Integer(Integer::new_constant(&type_, integer, span)?))

View File

@ -16,12 +16,15 @@
//! Enforces a relational `==` operator in a resolved Leo program.
use crate::{errors::ExpressionError, value::ConstrainedValue, GroupType};
use crate::{enforce_and, errors::ExpressionError, value::ConstrainedValue, GroupType};
use leo_typed::Span;
use snarkos_models::{
curves::{Field, PrimeField},
gadgets::{r1cs::ConstraintSystem, utilities::eq::EvaluateEqGadget},
gadgets::{
r1cs::ConstraintSystem,
utilities::{boolean::Boolean, eq::EvaluateEqGadget},
},
};
pub fn evaluate_eq<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>>(
@ -30,28 +33,64 @@ pub fn evaluate_eq<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<
right: ConstrainedValue<F, G>,
span: Span,
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
let mut unique_namespace = cs.ns(|| format!("evaluate {} == {} {}:{}", left, right, span.line, span.start));
let namespace_string = format!("evaluate {} == {} {}:{}", left, right, span.line, span.start);
let constraint_result = match (left, right) {
(ConstrainedValue::Address(address_1), ConstrainedValue::Address(address_2)) => {
let unique_namespace = cs.ns(|| namespace_string);
address_1.evaluate_equal(unique_namespace, &address_2)
}
(ConstrainedValue::Boolean(bool_1), ConstrainedValue::Boolean(bool_2)) => {
let unique_namespace = cs.ns(|| namespace_string);
bool_1.evaluate_equal(unique_namespace, &bool_2)
}
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
let unique_namespace = cs.ns(|| namespace_string);
num_1.evaluate_equal(unique_namespace, &num_2)
}
(ConstrainedValue::Field(field_1), ConstrainedValue::Field(field_2)) => {
let unique_namespace = cs.ns(|| namespace_string);
field_1.evaluate_equal(unique_namespace, &field_2)
}
(ConstrainedValue::Group(point_1), ConstrainedValue::Group(point_2)) => {
let unique_namespace = cs.ns(|| namespace_string);
point_1.evaluate_equal(unique_namespace, &point_2)
}
(ConstrainedValue::Array(arr_1), ConstrainedValue::Array(arr_2)) => {
let mut current = ConstrainedValue::Boolean(Boolean::constant(true));
for (i, (left, right)) in arr_1.into_iter().zip(arr_2.into_iter()).enumerate() {
let next = evaluate_eq(&mut cs.ns(|| format!("array[{}]", i)), left, right, span.clone())?;
current = enforce_and(
&mut cs.ns(|| format!("array result {}", i)),
current,
next,
span.clone(),
)?;
}
return Ok(current);
}
(ConstrainedValue::Tuple(tuple_1), ConstrainedValue::Tuple(tuple_2)) => {
let mut current = ConstrainedValue::Boolean(Boolean::constant(true));
for (i, (left, right)) in tuple_1.into_iter().zip(tuple_2.into_iter()).enumerate() {
let next = evaluate_eq(&mut cs.ns(|| format!("tuple_index {}", i)), left, right, span.clone())?;
current = enforce_and(
&mut cs.ns(|| format!("array result {}", i)),
current,
next,
span.clone(),
)?;
}
return Ok(current);
}
(ConstrainedValue::Unresolved(string), val_2) => {
let mut unique_namespace = cs.ns(|| namespace_string);
let val_1 = ConstrainedValue::from_other(string, &val_2, span.clone())?;
return evaluate_eq(&mut unique_namespace, val_1, val_2, span);
}
(val_1, ConstrainedValue::Unresolved(string)) => {
let mut unique_namespace = cs.ns(|| namespace_string);
let val_2 = ConstrainedValue::from_other(string, &val_1, span.clone())?;
return evaluate_eq(&mut unique_namespace, val_1, val_2, span);
}
@ -63,7 +102,7 @@ pub fn evaluate_eq<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<
}
};
let boolean = constraint_result.map_err(|e| ExpressionError::cannot_enforce(format!("evaluate equal"), e, span))?;
let boolean = constraint_result.map_err(|_| ExpressionError::cannot_evaluate(format!("=="), span))?;
Ok(ConstrainedValue::Boolean(boolean))
}

View File

@ -52,8 +52,7 @@ pub fn evaluate_ge<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<
}
};
let boolean = constraint_result
.map_err(|e| ExpressionError::cannot_enforce(format!("evaluate greater than or equal"), e, span))?;
let boolean = constraint_result.map_err(|_| ExpressionError::cannot_evaluate(format!(">="), span))?;
Ok(ConstrainedValue::Boolean(boolean))
}

View File

@ -52,8 +52,7 @@ pub fn evaluate_gt<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<
}
};
let boolean =
constraint_result.map_err(|e| ExpressionError::cannot_enforce(format!("evaluate greater than"), e, span))?;
let boolean = constraint_result.map_err(|_| ExpressionError::cannot_evaluate(format!(">"), span))?;
Ok(ConstrainedValue::Boolean(boolean))
}

View File

@ -52,8 +52,7 @@ pub fn evaluate_le<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<
}
};
let boolean = constraint_result
.map_err(|e| ExpressionError::cannot_enforce(format!("evaluate less than or equal"), e, span))?;
let boolean = constraint_result.map_err(|_| ExpressionError::cannot_evaluate(format!("<="), span))?;
Ok(ConstrainedValue::Boolean(boolean))
}

View File

@ -52,8 +52,7 @@ pub fn evaluate_lt<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<
}
};
let boolean =
constraint_result.map_err(|e| ExpressionError::cannot_enforce(format!("evaluate less than"), e, span))?;
let boolean = constraint_result.map_err(|_| ExpressionError::cannot_evaluate(format!("<"), span))?;
Ok(ConstrainedValue::Boolean(boolean))
}

View File

@ -21,6 +21,9 @@ extern crate thiserror;
pub mod compiler;
pub mod console;
pub use self::console::*;
pub mod constraints;
pub use self::constraints::*;
@ -37,9 +40,6 @@ pub use self::function::*;
pub mod import;
pub use self::import::*;
pub mod macro_;
pub use self::macro_::*;
pub mod output;
pub use self::output::*;

View File

@ -1,48 +0,0 @@
// Copyright (C) 2019-2020 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// 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/>.
//! Evaluates a macro in a compiled Leo program.
use crate::{errors::MacroError, program::ConstrainedProgram, GroupType};
use leo_typed::{FormattedMacro, MacroName};
use snarkos_models::{
curves::{Field, PrimeField},
gadgets::r1cs::ConstraintSystem,
};
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
pub fn evaluate_macro<CS: ConstraintSystem<F>>(
&mut self,
cs: &mut CS,
file_scope: String,
function_scope: String,
macro_: FormattedMacro,
) -> Result<(), MacroError> {
let string = macro_
.string
.map(|string| self.format(cs, file_scope, function_scope, string))
.unwrap_or(Ok("".to_string()))?;
match macro_.name {
MacroName::Debug(_) => log::debug!("{}", string),
MacroName::Error(_) => log::error!("{}", string),
MacroName::Print(_) => println!("{}", string),
}
Ok(())
}
}

View File

@ -1,21 +0,0 @@
// Copyright (C) 2019-2020 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// 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/>.
pub mod format;
pub use self::format::*;
pub mod macro_;
pub use self::macro_::*;

View File

@ -1,45 +0,0 @@
// Copyright (C) 2019-2020 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// 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/>.
//! Enforces an assert equals statement in a compiled Leo program.
use crate::{errors::StatementError, program::ConstrainedProgram, value::ConstrainedValue, GroupType};
use leo_typed::Span;
use snarkos_models::{
curves::{Field, PrimeField},
gadgets::{
r1cs::ConstraintSystem,
utilities::{boolean::Boolean, eq::ConditionalEqGadget},
},
};
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
pub fn enforce_assert_eq_statement<CS: ConstraintSystem<F>>(
&mut self,
cs: &mut CS,
indicator: Option<Boolean>,
left: &ConstrainedValue<F, G>,
right: &ConstrainedValue<F, G>,
span: Span,
) -> Result<(), StatementError> {
let condition = indicator.unwrap_or(Boolean::Constant(true));
let name_unique = format!("assert {} == {} {}:{}", left, right, span.line, span.start);
let result = left.conditional_enforce_equal(cs.ns(|| name_unique), right, &condition);
Ok(result.map_err(|_| StatementError::assertion_failed(left.to_string(), right.to_string(), span))?)
}
}

View File

@ -1,20 +0,0 @@
// Copyright (C) 2019-2020 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// 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/>.
//! Methods to enforce constraints on assert statements in a Leo program.
pub mod assert_eq;
pub use self::assert_eq::*;

View File

@ -16,9 +16,6 @@
//! Methods to enforce constraints on statements in a Leo program.
pub mod assert;
pub use self::assert::*;
pub mod assign;
pub use self::assign::*;

View File

@ -93,14 +93,8 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
results.append(&mut result);
}
Statement::AssertEq(left, right, span) => {
let (resolved_left, resolved_right) =
self.enforce_binary_expression(cs, file_scope, function_scope, None, left, right, span.clone())?;
self.enforce_assert_eq_statement(cs, indicator, &resolved_left, &resolved_right, span)?;
}
Statement::Macro(macro_) => {
self.evaluate_macro(cs, file_scope, function_scope, macro_)?;
Statement::Console(console) => {
self.evaluate_console_function_call(cs, file_scope, function_scope, indicator, console)?;
}
Statement::Expression(expression, span) => {
let expression_string = expression.to_string();

View File

@ -70,8 +70,8 @@ impl Address {
}
impl<F: Field + PrimeField> EvaluateEqGadget<F> for Address {
fn evaluate_equal<CS: ConstraintSystem<F>>(&self, _cs: CS, other: &Self) -> Result<Boolean, SynthesisError> {
Ok(Boolean::constant(self.eq(other)))
fn evaluate_equal<CS: ConstraintSystem<F>>(&self, _cs: CS, _other: &Self) -> Result<Boolean, SynthesisError> {
unimplemented!()
}
}
@ -97,15 +97,12 @@ impl<F: Field + PrimeField> ConditionalEqGadget<F> for Address {
if let Boolean::Constant(cond) = *condition {
cond_equal_helper(self, other, cond)
} else {
condition
.get_value()
.map(|cond| cond_equal_helper(self, other, cond))
.unwrap_or(Ok(()))
unimplemented!()
}
}
fn cost() -> usize {
0
unimplemented!()
}
}
@ -123,15 +120,12 @@ impl<F: Field + PrimeField> CondSelectGadget<F> for Address {
if let Boolean::Constant(cond) = *cond {
Ok(cond_select_helper(first, second, cond))
} else {
Ok(cond
.get_value()
.map(|cond| cond_select_helper(first, second, cond))
.unwrap_or(first.clone()))
unimplemented!()
}
}
fn cost() -> usize {
0
unimplemented!()
}
}

View File

@ -225,10 +225,17 @@ impl<F: Field + PrimeField> PartialOrd for FieldType<F> {
}
impl<F: Field + PrimeField> EvaluateEqGadget<F> for FieldType<F> {
fn evaluate_equal<CS: ConstraintSystem<F>>(&self, _cs: CS, other: &Self) -> Result<Boolean, SynthesisError> {
fn evaluate_equal<CS: ConstraintSystem<F>>(&self, mut _cs: CS, other: &Self) -> Result<Boolean, SynthesisError> {
match (self, other) {
(FieldType::Constant(first), FieldType::Constant(second)) => Ok(Boolean::constant(first.eq(second))),
_ => unimplemented!(),
// (FieldType::Allocated(first), FieldType::Allocated(second)) => first.evaluate_equal(cs, second),
// (FieldType::Constant(constant_value), FieldType::Allocated(allocated_value))
// | (FieldType::Allocated(allocated_value), FieldType::Constant(constant_value)) => {
// let allocated_constant_value =
// FpGadget::alloc(&mut cs.ns(|| format!("alloc constant for eq")), || Ok(constant_value))?;
// allocated_value.evaluate_equal(cs, &allocated_constant_value)
// }
}
}
}

View File

@ -15,7 +15,7 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{errors::GroupError, GroupType};
use leo_typed::{GroupCoordinate, GroupValue, Span};
use leo_typed::{GroupCoordinate, GroupTuple, GroupValue, Span};
use snarkos_curves::{
edwards_bls12::{EdwardsAffine, EdwardsParameters, Fq},
@ -24,7 +24,7 @@ use snarkos_curves::{
use snarkos_errors::gadgets::SynthesisError;
use snarkos_gadgets::curves::edwards_bls12::EdwardsBlsGadget;
use snarkos_models::{
curves::{AffineCurve, One, TEModelParameters},
curves::{AffineCurve, One, TEModelParameters, Zero},
gadgets::{
curves::{FieldGadget, FpGadget, GroupGadget},
r1cs::ConstraintSystem,
@ -134,7 +134,24 @@ impl GroupType<Fq> for EdwardsGroupType {
}
impl EdwardsGroupType {
pub fn edwards_affine_from_value(group: GroupValue) -> Result<EdwardsAffine, GroupError> {
pub fn edwards_affine_from_value(value: GroupValue) -> Result<EdwardsAffine, GroupError> {
match value {
GroupValue::Single(number, span) => Self::edwards_affine_from_single(number, span),
GroupValue::Tuple(tuple) => Self::edwards_affine_from_tuple(tuple),
}
}
pub fn edwards_affine_from_single(number: String, span: Span) -> Result<EdwardsAffine, GroupError> {
if number.eq("1") {
return Ok(edwards_affine_one());
} else if number.eq("0") {
return Ok(EdwardsAffine::zero());
} else {
Self::edwards_affine_from_x_str(number, span.clone(), None, span)
}
}
pub fn edwards_affine_from_tuple(group: GroupTuple) -> Result<EdwardsAffine, GroupError> {
let span = group.span;
let x = group.x;
let y = group.y;
@ -335,13 +352,49 @@ impl PartialEq for EdwardsGroupType {
impl Eq for EdwardsGroupType {}
// fn compare_allocated_edwards_bls_gadgets<CS: ConstraintSystem<Fq>>(
// mut cs: CS,
// first: &EdwardsBlsGadget,
// second: &EdwardsBlsGadget,
// ) -> Result<Boolean, SynthesisError> {
// // compare x coordinates
// let x_first = &first.x;
// let x_second = &second.x;
//
// let compare_x = x_first.evaluate_equal(&mut cs.ns(|| format!("compare x")), x_second)?;
//
// // compare y coordinates
// let y_first = &first.y;
// let y_second = &second.y;
//
// let compare_y = y_first.evaluate_equal(&mut cs.ns(|| format!("compare y")), y_second)?;
//
// Boolean::and(
// &mut cs.ns(|| format!("compare x and y results")),
// &compare_x,
// &compare_y,
// )
// }
impl EvaluateEqGadget<Fq> for EdwardsGroupType {
fn evaluate_equal<CS: ConstraintSystem<Fq>>(&self, _cs: CS, other: &Self) -> Result<Boolean, SynthesisError> {
fn evaluate_equal<CS: ConstraintSystem<Fq>>(&self, mut _cs: CS, other: &Self) -> Result<Boolean, SynthesisError> {
match (self, other) {
(EdwardsGroupType::Constant(self_value), EdwardsGroupType::Constant(other_value)) => {
Ok(Boolean::constant(self_value.eq(other_value)))
}
_ => unimplemented!(),
// (EdwardsGroupType::Allocated(first), EdwardsGroupType::Allocated(second)) => {
// compare_allocated_edwards_bls_gadgets(cs, first, second)
// }
// (EdwardsGroupType::Constant(constant_value), EdwardsGroupType::Allocated(allocated_value))
// | (EdwardsGroupType::Allocated(allocated_value), EdwardsGroupType::Constant(constant_value)) => {
// let allocated_constant_value =
// <EdwardsBlsGadget as AllocGadget<GroupAffine<EdwardsParameters>, Fq>>::alloc(
// &mut cs.ns(|| format!("alloc constant for eq")),
// || Ok(constant_value),
// )?;
// compare_allocated_edwards_bls_gadgets(cs, allocated_value, &allocated_constant_value)
// }
}
}
}

View File

@ -26,7 +26,7 @@ use crate::{
GroupType,
Integer,
};
use leo_typed::{Circuit, Function, Identifier, Span, Type};
use leo_typed::{Circuit, Function, GroupValue, Identifier, Span, Type};
use snarkos_errors::gadgets::SynthesisError;
use snarkos_models::{
@ -85,7 +85,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedValue<F, G> {
Type::Address => Ok(ConstrainedValue::Address(Address::new(value, span)?)),
Type::Boolean => Ok(ConstrainedValue::Boolean(new_bool_constant(value, span)?)),
Type::Field => Ok(ConstrainedValue::Field(FieldType::constant(value, span)?)),
Type::Group => Err(ValueError::implicit_group(span)),
Type::Group => Ok(ConstrainedValue::Group(G::constant(GroupValue::Single(value, span))?)),
Type::IntegerType(integer_type) => Ok(ConstrainedValue::Integer(Integer::new_constant(
integer_type,
value,

View File

@ -2,5 +2,5 @@ function main() {
let address_1 = address(aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8);
let address_2 = address(aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j9);
assert_eq!(address_1, address_2);
console.assert(address_1 == address_2);
}

View File

@ -2,5 +2,5 @@ function main() {
let address_1 = address(aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8);
let address_2 = address(aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8);
assert_eq!(address_1, address_2);
console.assert(address_1 == address_2);
}

View File

@ -1,3 +1,3 @@
function main(a: address, b: address, c: bool) {
assert_eq!(a == b, c);
console.assert(a == b == c);
}

View File

@ -1,5 +1,5 @@
function main(owner: address) {
let sender = address(aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8);
assert_eq!(owner, sender);
console.assert(owner == sender);
}

View File

@ -14,11 +14,10 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{assert_satisfied, expect_compiler_error, generate_main_input, parse_program};
use leo_typed::InputValue;
use crate::{assert_satisfied, expect_compiler_error, parse_program};
static TEST_ADDRESS_1: &'static str = "aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8";
static TEST_ADDRESS_2: &'static str = "aleo18qgam03qe483tdrcc3fkqwpp38ehff4a2xma6lu7hams6lfpgcpq3dq05r";
// static TEST_ADDRESS_1: &'static str = "aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8";
// static TEST_ADDRESS_2: &'static str = "aleo18qgam03qe483tdrcc3fkqwpp38ehff4a2xma6lu7hams6lfpgcpq3dq05r";
#[test]
fn test_valid() {
@ -68,72 +67,72 @@ fn test_implicit_invalid() {
let _output = expect_compiler_error(program);
}
#[test]
fn test_assert_eq_pass() {
let bytes = include_bytes!("assert_eq_pass.leo");
let program = parse_program(bytes).unwrap();
assert_satisfied(program);
}
#[test]
fn test_assert_eq_fail() {
let bytes = include_bytes!("assert_eq_fail.leo");
let program = parse_program(bytes).unwrap();
let _output = expect_compiler_error(program);
}
#[test]
fn test_ternary() {
let bytes = include_bytes!("ternary.leo");
let mut program = parse_program(bytes).unwrap();
let main_input = generate_main_input(vec![
("s", Some(InputValue::Boolean(true))),
("c", Some(InputValue::Address(TEST_ADDRESS_1.to_string()))),
]);
program.set_main_input(main_input);
assert_satisfied(program);
let mut program = parse_program(bytes).unwrap();
let main_input = generate_main_input(vec![
("s", Some(InputValue::Boolean(false))),
("c", Some(InputValue::Address(TEST_ADDRESS_2.to_string()))),
]);
program.set_main_input(main_input);
assert_satisfied(program);
}
#[test]
fn test_equal() {
let bytes = include_bytes!("equal.leo");
let mut program = parse_program(bytes).unwrap();
let main_input = generate_main_input(vec![
("a", Some(InputValue::Address(TEST_ADDRESS_1.to_string()))),
("b", Some(InputValue::Address(TEST_ADDRESS_1.to_string()))),
("c", Some(InputValue::Boolean(true))),
]);
program.set_main_input(main_input);
assert_satisfied(program);
let mut program = parse_program(bytes).unwrap();
let main_input = generate_main_input(vec![
("a", Some(InputValue::Address(TEST_ADDRESS_1.to_string()))),
("b", Some(InputValue::Address(TEST_ADDRESS_2.to_string()))),
("c", Some(InputValue::Boolean(false))),
]);
program.set_main_input(main_input);
assert_satisfied(program);
}
// #[test]
// fn test_assert_eq_pass() {
// let bytes = include_bytes!("assert_eq_pass.leo");
// let program = parse_program(bytes).unwrap();
//
// assert_satisfied(program);
// }
//
// #[test]
// fn test_assert_eq_fail() {
// let bytes = include_bytes!("assert_eq_fail.leo");
// let program = parse_program(bytes).unwrap();
//
// let _output = expect_compiler_error(program);
// }
//
// #[test]
// fn test_ternary() {
// let bytes = include_bytes!("ternary.leo");
// let mut program = parse_program(bytes).unwrap();
//
// let main_input = generate_main_input(vec![
// ("s", Some(InputValue::Boolean(true))),
// ("c", Some(InputValue::Address(TEST_ADDRESS_1.to_string()))),
// ]);
//
// program.set_main_input(main_input);
//
// assert_satisfied(program);
//
// let mut program = parse_program(bytes).unwrap();
//
// let main_input = generate_main_input(vec![
// ("s", Some(InputValue::Boolean(false))),
// ("c", Some(InputValue::Address(TEST_ADDRESS_2.to_string()))),
// ]);
//
// program.set_main_input(main_input);
//
// assert_satisfied(program);
// }
//
// #[test]
// fn test_equal() {
// let bytes = include_bytes!("equal.leo");
// let mut program = parse_program(bytes).unwrap();
//
// let main_input = generate_main_input(vec![
// ("a", Some(InputValue::Address(TEST_ADDRESS_1.to_string()))),
// ("b", Some(InputValue::Address(TEST_ADDRESS_1.to_string()))),
// ("c", Some(InputValue::Boolean(true))),
// ]);
//
// program.set_main_input(main_input);
//
// assert_satisfied(program);
//
// let mut program = parse_program(bytes).unwrap();
//
// let main_input = generate_main_input(vec![
// ("a", Some(InputValue::Address(TEST_ADDRESS_1.to_string()))),
// ("b", Some(InputValue::Address(TEST_ADDRESS_2.to_string()))),
// ("c", Some(InputValue::Boolean(false))),
// ]);
//
// program.set_main_input(main_input);
//
// assert_satisfied(program);
// }

View File

@ -4,5 +4,5 @@ function main(s: bool, c: address) {
let r = if s? a: b;
assert_eq!(r, c);
console.assert(r == c);
}

View File

@ -1,3 +1,3 @@
function main(a: u8[3]) {
assert_eq!(a, [1u8; 3]);
console.assert(a == [1u8; 3]);
}

View File

@ -1,3 +1,3 @@
function main(a: u8[3]) {
assert_eq!(a, [1u8; -3]);
console.assert(a == [1u8; -3]);
}

View File

@ -1,3 +1,3 @@
function main(a: u8[3]) {
assert_eq!(a, [1u8, 1u8, 1u8]);
console.assert(a == [1u8, 1u8, 1u8]);
}

View File

@ -24,14 +24,14 @@ use crate::{
};
pub fn output_ones(program: EdwardsTestCompiler) {
let expected = include_bytes!("output_/registers_ones.out");
let expected = include_bytes!("output/registers_ones.out");
let actual = get_output(program);
assert!(expected.eq(actual.bytes().as_slice()));
}
pub fn output_zeros(program: EdwardsTestCompiler) {
let expected = include_bytes!("output_/registers_zeros.out");
let expected = include_bytes!("output/registers_zeros.out");
let actual = get_output(program);
assert!(expected.eq(actual.bytes().as_slice()));

View File

@ -4,5 +4,5 @@ function main() {
const b: u32[3][2] = [[0; 3]; 2]; // initializer
assert_eq!(a, b);
console.assert(a == b);
}

View File

@ -2,5 +2,5 @@
function main(a: u8[3]) {
let b = [1u8; 4];
assert_eq!(a, b[0..3]);
console.assert(a == b[0..3]);
}

View File

@ -2,5 +2,5 @@
function main(a: u8[3]) {
let b = [1u8, 1u8];
assert_eq!(a, [1u8, ...b]);
console.assert(a == [1u8, ...b]);
}

View File

@ -4,5 +4,5 @@ function main() {
const b = false || a;
const c = !(true && b);
assert_eq!(c, false);
console.assert(c == false);
}

View File

@ -1,3 +1,3 @@
function main(a: bool, b: bool) {
assert_eq!(a, b);
console.assert(a == b);
}

View File

@ -1,5 +1,5 @@
function main() {
let a = false && false;
assert_eq!(a, false);
console.assert(a == false);
}

View File

@ -1,5 +1,5 @@
function main() {
let a = false || false;
assert_eq!(a, false);
console.assert(a == false);
}

View File

@ -17,7 +17,6 @@
use crate::{
assert_satisfied,
expect_compiler_error,
expect_synthesis_error,
get_output,
parse_program,
parse_program_with_input,
@ -26,14 +25,14 @@ use crate::{
use leo_compiler::errors::{BooleanError, CompilerError, ExpressionError, FunctionError, StatementError};
pub fn output_true(program: EdwardsTestCompiler) {
let expected = include_bytes!("output_/registers_true.out");
let expected = include_bytes!("output/registers_true.out");
let actual = get_output(program);
assert_eq!(expected, actual.bytes().as_slice());
}
pub fn output_false(program: EdwardsTestCompiler) {
let expected = include_bytes!("output_/registers_false.out");
let expected = include_bytes!("output/registers_false.out");
let actual = get_output(program);
assert_eq!(expected, actual.bytes().as_slice());
@ -65,7 +64,7 @@ fn test_input_fail() {
let program = parse_program_with_input(program_bytes, input_bytes).unwrap();
expect_synthesis_error(program);
expect_compiler_error(program);
}
#[test]
@ -108,7 +107,7 @@ fn test_not_u32() {
let bytes = include_bytes!("not_u32.leo");
let program = parse_program(bytes).unwrap();
fail_boolean_statement(program);
expect_compiler_error(program);
}
// Boolean or ||

View File

@ -1,3 +1,3 @@
function main() {
assert_eq!(!false, true);
console.assert(!false == true);
}

View File

@ -1,3 +1,3 @@
function main() {
assert_eq!(!true, false);
console.assert(!true == false);
}

View File

@ -1,3 +1,3 @@
function main() -> bool {
assert_eq!(!1u32, 0u32);
console.assert(!1u32 == 0u32);
}

View File

@ -1,5 +1,5 @@
function main() {
let a = true && false;
assert_eq!(a, false);
console.assert(a == false);
}

View File

@ -1,5 +1,5 @@
function main() {
let a = true && true;
assert_eq!(a, true);
console.assert(a == true);
}

View File

@ -1,5 +1,5 @@
function main() {
let a = true || false;
assert_eq!(a, true);
console.assert(a == true);
}

View File

@ -1,5 +1,5 @@
function main() {
let a = true || true;
assert_eq!(a, true);
console.assert(a == true);
}

View File

@ -5,5 +5,5 @@ circuit Foo {
function main() {
let a = Foo { x: 1u32 };
assert_eq!(a.x, 1u32);
console.assert(a.x == 1u32);
}

View File

@ -11,5 +11,5 @@ function main() {
let b = a.foo + Foo::bar();
assert_eq!(b, 2u32);
console.assert(b == 2u32);
}

View File

@ -7,5 +7,5 @@ circuit Foo {
function main() {
let a = Foo { };
assert_eq!(a.echo(1u32), 1u32);
console.assert(a.echo(1u32) == 1u32);
}

View File

@ -14,5 +14,5 @@ function main() {
let a = Foo { x: 1u32 };
let b = a.call_add_x(1u32);
assert_eq!(b, 2u32);
console.assert(b == 2u32);
}

View File

@ -7,5 +7,5 @@ circuit Foo {
function main() {
let a = Foo::echo(1u32);
assert_eq!(a, 1u32);
console.assert(a == 1u32);
}

View File

@ -21,5 +21,7 @@ function main() {
let pedersen = PedersenHash::new(parameters);
let input: bool[512] = [true; 512];
assert_eq!(pedersen.hash(input), 0u32);
let res = pedersen.hash(input);
console.assert(res == 0u32);
}

View File

@ -10,5 +10,5 @@ function main() {
let a = Foo { f: 1u32 };
let b = a.bar();
assert_eq!(b, 1u32);
console.assert(b == 1u32);
}

View File

@ -0,0 +1,3 @@
function main(a: bool) {
console.assert(a == true);
}

View File

@ -0,0 +1,7 @@
function main(a: bool) {
if a {
console.assert(a == true);
} else {
console.assert(a == false);
}
}

View File

@ -0,0 +1,3 @@
function main() {
console.debug("hello debug");
}

View File

@ -0,0 +1,3 @@
function main() {
console.error("hello error");
}

View File

@ -0,0 +1,3 @@
function main() {
console.log("hello world");
}

View File

@ -0,0 +1,3 @@
function main() {
console.log( hello );
}

View File

@ -0,0 +1,3 @@
function main(a: bool) {
console.log("a = {}", a);
}

View File

@ -0,0 +1,3 @@
function main() {
console.log("{}", 1u32);
}

View File

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

View File

@ -0,0 +1,3 @@
function main() {
console.log("", 1u32);
}

Some files were not shown because too many files have changed in this diff Show More