mirror of
https://github.com/AleoHQ/leo.git
synced 2024-11-25 05:36:50 +03:00
Merge branch 'master' of https://github.com/AleoHQ/leo into feature/update_command
This commit is contained in:
commit
3a233add99
133
README.md
133
README.md
@ -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)
|
||||
|
21
ast/src/console/console_assert.rs
Normal file
21
ast/src/console/console_assert.rs
Normal 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)
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
21
ast/src/console/console_error.rs
Normal file
21
ast/src/console/console_error.rs
Normal 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)
|
||||
}
|
||||
}
|
28
ast/src/console/console_function.rs
Normal file
28
ast/src/console/console_function.rs
Normal 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),
|
||||
}
|
||||
}
|
||||
}
|
28
ast/src/console/console_function_call.rs
Normal file
28
ast/src/console/console_function_call.rs
Normal 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)
|
||||
}
|
||||
}
|
@ -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")
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
@ -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
29
ast/src/console/mod.rs
Normal 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::*;
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
@ -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
|
||||
)
|
||||
}
|
||||
}
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
@ -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, "!")
|
||||
}
|
||||
}
|
@ -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::*;
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
@ -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::*;
|
||||
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
@ -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> {
|
||||
|
50
compiler/src/console/assert.rs
Normal file
50
compiler/src/console/assert.rs
Normal 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(())
|
||||
}
|
||||
}
|
62
compiler/src/console/console.rs
Normal file
62
compiler/src/console/console.rs
Normal 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
|
||||
}
|
@ -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(),
|
8
compiler/src/console/mod.rs
Normal file
8
compiler/src/console/mod.rs
Normal 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::*;
|
53
compiler/src/errors/console.rs
Normal file
53
compiler/src/errors/console.rs
Normal 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)
|
||||
}
|
||||
}
|
@ -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);
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
@ -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::*;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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,
|
||||
);
|
||||
|
||||
|
@ -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,
|
||||
);
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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,
|
||||
);
|
||||
|
||||
|
@ -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)?))
|
||||
|
@ -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))
|
||||
}
|
||||
|
@ -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))
|
||||
}
|
||||
|
@ -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))
|
||||
}
|
||||
|
@ -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))
|
||||
}
|
||||
|
@ -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))
|
||||
}
|
||||
|
@ -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::*;
|
||||
|
||||
|
@ -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(())
|
||||
}
|
||||
}
|
@ -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_::*;
|
@ -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))?)
|
||||
}
|
||||
}
|
@ -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::*;
|
@ -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::*;
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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!()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
@ -1,3 +1,3 @@
|
||||
function main(a: address, b: address, c: bool) {
|
||||
assert_eq!(a == b, c);
|
||||
console.assert(a == b == c);
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
function main(owner: address) {
|
||||
let sender = address(aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8);
|
||||
|
||||
assert_eq!(owner, sender);
|
||||
console.assert(owner == sender);
|
||||
}
|
@ -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);
|
||||
// }
|
||||
|
@ -4,5 +4,5 @@ function main(s: bool, c: address) {
|
||||
|
||||
let r = if s? a: b;
|
||||
|
||||
assert_eq!(r, c);
|
||||
console.assert(r == c);
|
||||
}
|
@ -1,3 +1,3 @@
|
||||
function main(a: u8[3]) {
|
||||
assert_eq!(a, [1u8; 3]);
|
||||
console.assert(a == [1u8; 3]);
|
||||
}
|
@ -1,3 +1,3 @@
|
||||
function main(a: u8[3]) {
|
||||
assert_eq!(a, [1u8; -3]);
|
||||
console.assert(a == [1u8; -3]);
|
||||
}
|
@ -1,3 +1,3 @@
|
||||
function main(a: u8[3]) {
|
||||
assert_eq!(a, [1u8, 1u8, 1u8]);
|
||||
console.assert(a == [1u8, 1u8, 1u8]);
|
||||
}
|
@ -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()));
|
||||
|
@ -4,5 +4,5 @@ function main() {
|
||||
|
||||
const b: u32[3][2] = [[0; 3]; 2]; // initializer
|
||||
|
||||
assert_eq!(a, b);
|
||||
console.assert(a == b);
|
||||
}
|
@ -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]);
|
||||
}
|
||||
|
@ -2,5 +2,5 @@
|
||||
function main(a: u8[3]) {
|
||||
let b = [1u8, 1u8];
|
||||
|
||||
assert_eq!(a, [1u8, ...b]);
|
||||
console.assert(a == [1u8, ...b]);
|
||||
}
|
@ -4,5 +4,5 @@ function main() {
|
||||
const b = false || a;
|
||||
const c = !(true && b);
|
||||
|
||||
assert_eq!(c, false);
|
||||
console.assert(c == false);
|
||||
}
|
@ -1,3 +1,3 @@
|
||||
function main(a: bool, b: bool) {
|
||||
assert_eq!(a, b);
|
||||
console.assert(a == b);
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
function main() {
|
||||
let a = false && false;
|
||||
|
||||
assert_eq!(a, false);
|
||||
console.assert(a == false);
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
function main() {
|
||||
let a = false || false;
|
||||
|
||||
assert_eq!(a, false);
|
||||
console.assert(a == false);
|
||||
}
|
@ -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 ||
|
||||
|
@ -1,3 +1,3 @@
|
||||
function main() {
|
||||
assert_eq!(!false, true);
|
||||
console.assert(!false == true);
|
||||
}
|
@ -1,3 +1,3 @@
|
||||
function main() {
|
||||
assert_eq!(!true, false);
|
||||
console.assert(!true == false);
|
||||
}
|
@ -1,3 +1,3 @@
|
||||
function main() -> bool {
|
||||
assert_eq!(!1u32, 0u32);
|
||||
console.assert(!1u32 == 0u32);
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
function main() {
|
||||
let a = true && false;
|
||||
|
||||
assert_eq!(a, false);
|
||||
console.assert(a == false);
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
function main() {
|
||||
let a = true && true;
|
||||
|
||||
assert_eq!(a, true);
|
||||
console.assert(a == true);
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
function main() {
|
||||
let a = true || false;
|
||||
|
||||
assert_eq!(a, true);
|
||||
console.assert(a == true);
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
function main() {
|
||||
let a = true || true;
|
||||
|
||||
assert_eq!(a, true);
|
||||
console.assert(a == true);
|
||||
}
|
@ -5,5 +5,5 @@ circuit Foo {
|
||||
function main() {
|
||||
let a = Foo { x: 1u32 };
|
||||
|
||||
assert_eq!(a.x, 1u32);
|
||||
console.assert(a.x == 1u32);
|
||||
}
|
@ -11,5 +11,5 @@ function main() {
|
||||
|
||||
let b = a.foo + Foo::bar();
|
||||
|
||||
assert_eq!(b, 2u32);
|
||||
console.assert(b == 2u32);
|
||||
}
|
||||
|
@ -7,5 +7,5 @@ circuit Foo {
|
||||
function main() {
|
||||
let a = Foo { };
|
||||
|
||||
assert_eq!(a.echo(1u32), 1u32);
|
||||
console.assert(a.echo(1u32) == 1u32);
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
@ -7,5 +7,5 @@ circuit Foo {
|
||||
function main() {
|
||||
let a = Foo::echo(1u32);
|
||||
|
||||
assert_eq!(a, 1u32);
|
||||
console.assert(a == 1u32);
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
@ -10,5 +10,5 @@ function main() {
|
||||
let a = Foo { f: 1u32 };
|
||||
let b = a.bar();
|
||||
|
||||
assert_eq!(b, 1u32);
|
||||
console.assert(b == 1u32);
|
||||
}
|
3
compiler/tests/console/assert.leo
Normal file
3
compiler/tests/console/assert.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: bool) {
|
||||
console.assert(a == true);
|
||||
}
|
7
compiler/tests/console/conditional_assert.leo
Normal file
7
compiler/tests/console/conditional_assert.leo
Normal file
@ -0,0 +1,7 @@
|
||||
function main(a: bool) {
|
||||
if a {
|
||||
console.assert(a == true);
|
||||
} else {
|
||||
console.assert(a == false);
|
||||
}
|
||||
}
|
3
compiler/tests/console/debug.leo
Normal file
3
compiler/tests/console/debug.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main() {
|
||||
console.debug("hello debug");
|
||||
}
|
3
compiler/tests/console/error.leo
Normal file
3
compiler/tests/console/error.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main() {
|
||||
console.error("hello error");
|
||||
}
|
3
compiler/tests/console/log.leo
Normal file
3
compiler/tests/console/log.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main() {
|
||||
console.log("hello world");
|
||||
}
|
3
compiler/tests/console/log_fail.leo
Normal file
3
compiler/tests/console/log_fail.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main() {
|
||||
console.log( hello );
|
||||
}
|
3
compiler/tests/console/log_input.leo
Normal file
3
compiler/tests/console/log_input.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main(a: bool) {
|
||||
console.log("a = {}", a);
|
||||
}
|
3
compiler/tests/console/log_parameter.leo
Normal file
3
compiler/tests/console/log_parameter.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main() {
|
||||
console.log("{}", 1u32);
|
||||
}
|
3
compiler/tests/console/log_parameter_fail_empty.leo
Normal file
3
compiler/tests/console/log_parameter_fail_empty.leo
Normal file
@ -0,0 +1,3 @@
|
||||
function main() {
|
||||
console.log("{}");
|
||||
}
|
3
compiler/tests/console/log_parameter_fail_none.leo
Normal file
3
compiler/tests/console/log_parameter_fail_none.leo
Normal 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
Loading…
Reference in New Issue
Block a user