mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-11-28 01:01:53 +03:00
merge function input self changes
This commit is contained in:
commit
0f91630a9f
43
.github/workflows/ci.yml
vendored
43
.github/workflows/ci.yml
vendored
@ -31,6 +31,49 @@ jobs:
|
|||||||
command: fmt
|
command: fmt
|
||||||
args: --all -- --check
|
args: --all -- --check
|
||||||
|
|
||||||
|
clippy:
|
||||||
|
name: Clippy
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
RUSTFLAGS: -Dwarnings
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
rust:
|
||||||
|
- stable
|
||||||
|
- nightly
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Install Rust (${{ matrix.rust }})
|
||||||
|
uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
profile: minimal
|
||||||
|
toolchain: ${{ matrix.rust }}
|
||||||
|
override: true
|
||||||
|
components: clippy
|
||||||
|
|
||||||
|
- name: Check examples
|
||||||
|
uses: actions-rs/cargo@v1
|
||||||
|
with:
|
||||||
|
command: clippy
|
||||||
|
args: --examples --all
|
||||||
|
|
||||||
|
- name: Check examples with all features on stable
|
||||||
|
uses: actions-rs/cargo@v1
|
||||||
|
with:
|
||||||
|
command: clippy
|
||||||
|
args: --examples --all-features --all
|
||||||
|
if: matrix.rust == 'stable'
|
||||||
|
|
||||||
|
- name: Check benchmarks on nightly
|
||||||
|
uses: actions-rs/cargo@v1
|
||||||
|
with:
|
||||||
|
command: clippy
|
||||||
|
args: --all-features --examples --all --benches
|
||||||
|
if: matrix.rust == 'nightly'
|
||||||
|
|
||||||
test:
|
test:
|
||||||
name: Test
|
name: Test
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
26
Cargo.lock
generated
26
Cargo.lock
generated
@ -1296,7 +1296,7 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "leo-ast"
|
name = "leo-ast"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"criterion",
|
"criterion",
|
||||||
"leo-grammar",
|
"leo-grammar",
|
||||||
@ -1310,7 +1310,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "leo-compiler"
|
name = "leo-compiler"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bincode",
|
"bincode",
|
||||||
"hex",
|
"hex",
|
||||||
@ -1345,7 +1345,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "leo-core"
|
name = "leo-core"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"leo-ast",
|
"leo-ast",
|
||||||
"leo-gadgets",
|
"leo-gadgets",
|
||||||
@ -1361,7 +1361,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "leo-gadgets"
|
name = "leo-gadgets"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"criterion",
|
"criterion",
|
||||||
"rand",
|
"rand",
|
||||||
@ -1374,7 +1374,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "leo-grammar"
|
name = "leo-grammar"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"criterion",
|
"criterion",
|
||||||
"from-pest",
|
"from-pest",
|
||||||
@ -1390,7 +1390,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "leo-imports"
|
name = "leo-imports"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"leo-ast",
|
"leo-ast",
|
||||||
"leo-grammar",
|
"leo-grammar",
|
||||||
@ -1400,7 +1400,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "leo-input"
|
name = "leo-input"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"from-pest",
|
"from-pest",
|
||||||
"pest",
|
"pest",
|
||||||
@ -1417,7 +1417,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "leo-lang"
|
name = "leo-lang"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"colored",
|
"colored",
|
||||||
@ -1458,11 +1458,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "leo-linter"
|
name = "leo-linter"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "leo-package"
|
name = "leo-package"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"serde",
|
"serde",
|
||||||
@ -1476,7 +1476,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "leo-state"
|
name = "leo-state"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"leo-ast",
|
"leo-ast",
|
||||||
"leo-input",
|
"leo-input",
|
||||||
@ -1495,7 +1495,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "leo-symbol-table"
|
name = "leo-symbol-table"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"leo-ast",
|
"leo-ast",
|
||||||
"leo-core",
|
"leo-core",
|
||||||
@ -1507,7 +1507,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "leo-type-inference"
|
name = "leo-type-inference"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"leo-ast",
|
"leo-ast",
|
||||||
"leo-grammar",
|
"leo-grammar",
|
||||||
|
18
Cargo.toml
18
Cargo.toml
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "leo-lang"
|
name = "leo-lang"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
authors = [ "The Aleo Team <hello@aleo.org>" ]
|
authors = [ "The Aleo Team <hello@aleo.org>" ]
|
||||||
description = "The Leo programming language"
|
description = "The Leo programming language"
|
||||||
homepage = "https://aleo.org"
|
homepage = "https://aleo.org"
|
||||||
@ -37,36 +37,36 @@ members = [
|
|||||||
"package",
|
"package",
|
||||||
"state",
|
"state",
|
||||||
"symbol-table",
|
"symbol-table",
|
||||||
"type-inference",
|
"type-inference"
|
||||||
]
|
]
|
||||||
|
|
||||||
[dependencies.leo-ast]
|
[dependencies.leo-ast]
|
||||||
path = "./ast"
|
path = "./ast"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
|
|
||||||
[dependencies.leo-compiler]
|
[dependencies.leo-compiler]
|
||||||
path = "./compiler"
|
path = "./compiler"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
|
|
||||||
[dependencies.leo-gadgets]
|
[dependencies.leo-gadgets]
|
||||||
path = "./gadgets"
|
path = "./gadgets"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
|
|
||||||
[dependencies.leo-imports]
|
[dependencies.leo-imports]
|
||||||
path = "./imports"
|
path = "./imports"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
|
|
||||||
[dependencies.leo-input]
|
[dependencies.leo-input]
|
||||||
path = "./input"
|
path = "./input"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
|
|
||||||
[dependencies.leo-package]
|
[dependencies.leo-package]
|
||||||
path = "./package"
|
path = "./package"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
|
|
||||||
[dependencies.leo-state]
|
[dependencies.leo-state]
|
||||||
path = "./state"
|
path = "./state"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
|
|
||||||
[dependencies.snarkos-algorithms]
|
[dependencies.snarkos-algorithms]
|
||||||
version = "1.1.3"
|
version = "1.1.3"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "leo-ast"
|
name = "leo-ast"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
authors = [ "The Aleo Team <hello@aleo.org>" ]
|
authors = [ "The Aleo Team <hello@aleo.org>" ]
|
||||||
description = "Core AST of the Leo programming language"
|
description = "Core AST of the Leo programming language"
|
||||||
homepage = "https://aleo.org"
|
homepage = "https://aleo.org"
|
||||||
@ -28,11 +28,11 @@ harness = false
|
|||||||
|
|
||||||
[dependencies.leo-grammar]
|
[dependencies.leo-grammar]
|
||||||
path = "../grammar"
|
path = "../grammar"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
|
|
||||||
[dependencies.leo-input]
|
[dependencies.leo-input]
|
||||||
path = "../input"
|
path = "../input"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
|
|
||||||
[dependencies.snarkos-errors]
|
[dependencies.snarkos-errors]
|
||||||
version = "1.1.3"
|
version = "1.1.3"
|
||||||
|
@ -20,64 +20,64 @@ use leo_grammar::Grammar;
|
|||||||
use criterion::{criterion_group, criterion_main, Criterion};
|
use criterion::{criterion_group, criterion_main, Criterion};
|
||||||
use std::{path::Path, time::Duration};
|
use std::{path::Path, time::Duration};
|
||||||
|
|
||||||
fn ast<'ast>(ast: &Grammar<'ast>) -> Ast {
|
fn ast(ast: &Grammar) -> Ast {
|
||||||
Ast::new("leo_tree", &ast)
|
Ast::new("leo_tree", &ast)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bench_big_if_else(c: &mut Criterion) {
|
fn bench_big_if_else(c: &mut Criterion) {
|
||||||
let filepath = Path::new("./big_if_else.leo").to_path_buf();
|
let filepath = Path::new("./big_if_else.leo").to_path_buf();
|
||||||
let program_string = include_str!("./big_if_else.leo");
|
let program_string = include_str!("./big_if_else.leo");
|
||||||
let ast = Grammar::new(&filepath, program_string).unwrap();
|
let grammar = Grammar::new(&filepath, program_string).unwrap();
|
||||||
|
|
||||||
c.bench_function("Ast::big_if_else", |b| b.iter(|| ast(&ast)));
|
c.bench_function("Ast::big_if_else", |b| b.iter(|| ast(&grammar)));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bench_big_ternary(c: &mut Criterion) {
|
fn bench_big_ternary(c: &mut Criterion) {
|
||||||
let filepath = Path::new("./big_ternary.leo").to_path_buf();
|
let filepath = Path::new("./big_ternary.leo").to_path_buf();
|
||||||
let program_string = include_str!("./big_ternary.leo");
|
let program_string = include_str!("./big_ternary.leo");
|
||||||
let ast = Grammar::new(&filepath, program_string).unwrap();
|
let grammar = Grammar::new(&filepath, program_string).unwrap();
|
||||||
|
|
||||||
c.bench_function("Ast::big_ternary", |b| b.iter(|| ast(&ast)));
|
c.bench_function("Ast::big_ternary", |b| b.iter(|| ast(&grammar)));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bench_big_circuit(c: &mut Criterion) {
|
fn bench_big_circuit(c: &mut Criterion) {
|
||||||
let filepath = Path::new("./big_circuit.leo").to_path_buf();
|
let filepath = Path::new("./big_circuit.leo").to_path_buf();
|
||||||
let program_string = include_str!("./big_circuit.leo");
|
let program_string = include_str!("./big_circuit.leo");
|
||||||
let ast = Grammar::new(&filepath, program_string).unwrap();
|
let grammar = Grammar::new(&filepath, program_string).unwrap();
|
||||||
|
|
||||||
c.bench_function("Ast::big_circuit", |b| b.iter(|| ast(&ast)));
|
c.bench_function("Ast::big_circuit", |b| b.iter(|| ast(&grammar)));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bench_long_expr(c: &mut Criterion) {
|
fn bench_long_expr(c: &mut Criterion) {
|
||||||
let filepath = Path::new("./long_expr.leo").to_path_buf();
|
let filepath = Path::new("./long_expr.leo").to_path_buf();
|
||||||
let program_string = include_str!("./long_expr.leo");
|
let program_string = include_str!("./long_expr.leo");
|
||||||
let ast = Grammar::new(&filepath, program_string).unwrap();
|
let grammar = Grammar::new(&filepath, program_string).unwrap();
|
||||||
|
|
||||||
c.bench_function("Ast::long_expr", |b| b.iter(|| ast(&ast)));
|
c.bench_function("Ast::long_expr", |b| b.iter(|| ast(&grammar)));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bench_long_array(c: &mut Criterion) {
|
fn bench_long_array(c: &mut Criterion) {
|
||||||
let filepath = Path::new("./long_array.leo").to_path_buf();
|
let filepath = Path::new("./long_array.leo").to_path_buf();
|
||||||
let program_string = include_str!("./long_array.leo");
|
let program_string = include_str!("./long_array.leo");
|
||||||
let ast = Grammar::new(&filepath, program_string).unwrap();
|
let grammar = Grammar::new(&filepath, program_string).unwrap();
|
||||||
|
|
||||||
c.bench_function("Ast::long_array", |b| b.iter(|| ast(&ast)));
|
c.bench_function("Ast::long_array", |b| b.iter(|| ast(&grammar)));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bench_many_foos(c: &mut Criterion) {
|
fn bench_many_foos(c: &mut Criterion) {
|
||||||
let filepath = Path::new("./many_foos.leo").to_path_buf();
|
let filepath = Path::new("./many_foos.leo").to_path_buf();
|
||||||
let program_string = include_str!("./many_foos.leo");
|
let program_string = include_str!("./many_foos.leo");
|
||||||
let ast = Grammar::new(&filepath, program_string).unwrap();
|
let grammar = Grammar::new(&filepath, program_string).unwrap();
|
||||||
|
|
||||||
c.bench_function("Ast::many_foos", |b| b.iter(|| ast(&ast)));
|
c.bench_function("Ast::many_foos", |b| b.iter(|| ast(&grammar)));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bench_many_assigns(c: &mut Criterion) {
|
fn bench_many_assigns(c: &mut Criterion) {
|
||||||
let filepath = Path::new("./many_assigns.leo").to_path_buf();
|
let filepath = Path::new("./many_assigns.leo").to_path_buf();
|
||||||
let program_string = include_str!("./many_assigns.leo");
|
let program_string = include_str!("./many_assigns.leo");
|
||||||
let ast = Grammar::new(&filepath, program_string).unwrap();
|
let grammar = Grammar::new(&filepath, program_string).unwrap();
|
||||||
|
|
||||||
c.bench_function("Ast::many_assigns", |b| b.iter(|| ast(&ast)));
|
c.bench_function("Ast::many_assigns", |b| b.iter(|| ast(&grammar)));
|
||||||
}
|
}
|
||||||
|
|
||||||
criterion_group!(
|
criterion_group!(
|
||||||
|
@ -15,10 +15,9 @@
|
|||||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use crate::{Function, Identifier, Type};
|
use crate::{Function, Identifier, Type};
|
||||||
use leo_grammar::circuits::{
|
use leo_grammar::{
|
||||||
CircuitFunction as GrammarCircuitFunction,
|
circuits::{CircuitMember as GrammarCircuitMember, CircuitVariableDefinition as GrammarCircuitVariableDefinition},
|
||||||
CircuitMember as GrammarCircuitMember,
|
functions::Function as GrammarFunction,
|
||||||
CircuitVariableDefinition as GrammarCircuitVariableDefinition,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@ -26,28 +25,24 @@ use std::fmt;
|
|||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub enum CircuitMember {
|
pub enum CircuitMember {
|
||||||
// (is_mutable, variable_name, variable_type)
|
// (variable_name, variable_type)
|
||||||
CircuitVariable(bool, Identifier, Type),
|
CircuitVariable(Identifier, Type),
|
||||||
// (is_static, function)
|
// (function)
|
||||||
CircuitFunction(bool, Function),
|
CircuitFunction(Function),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ast> From<GrammarCircuitVariableDefinition<'ast>> for CircuitMember {
|
impl<'ast> From<GrammarCircuitVariableDefinition<'ast>> for CircuitMember {
|
||||||
fn from(circuit_value: GrammarCircuitVariableDefinition<'ast>) -> Self {
|
fn from(circuit_value: GrammarCircuitVariableDefinition<'ast>) -> Self {
|
||||||
CircuitMember::CircuitVariable(
|
CircuitMember::CircuitVariable(
|
||||||
circuit_value.mutable.is_some(),
|
|
||||||
Identifier::from(circuit_value.identifier),
|
Identifier::from(circuit_value.identifier),
|
||||||
Type::from(circuit_value.type_),
|
Type::from(circuit_value.type_),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ast> From<GrammarCircuitFunction<'ast>> for CircuitMember {
|
impl<'ast> From<GrammarFunction<'ast>> for CircuitMember {
|
||||||
fn from(circuit_function: GrammarCircuitFunction<'ast>) -> Self {
|
fn from(circuit_function: GrammarFunction<'ast>) -> Self {
|
||||||
CircuitMember::CircuitFunction(
|
CircuitMember::CircuitFunction(Function::from(circuit_function))
|
||||||
circuit_function._static.is_some(),
|
|
||||||
Function::from(circuit_function.function),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,16 +58,10 @@ impl<'ast> From<GrammarCircuitMember<'ast>> for CircuitMember {
|
|||||||
impl fmt::Display for CircuitMember {
|
impl fmt::Display for CircuitMember {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
CircuitMember::CircuitVariable(ref mutable, ref identifier, ref type_) => {
|
CircuitMember::CircuitVariable(ref identifier, ref type_) => {
|
||||||
if *mutable {
|
|
||||||
write!(f, "mut ")?;
|
|
||||||
}
|
|
||||||
write!(f, "{}: {}", identifier, type_)
|
write!(f, "{}: {}", identifier, type_)
|
||||||
}
|
}
|
||||||
CircuitMember::CircuitFunction(ref static_, ref function) => {
|
CircuitMember::CircuitFunction(ref function) => {
|
||||||
if *static_ {
|
|
||||||
write!(f, "static ")?;
|
|
||||||
}
|
|
||||||
write!(f, "{}", function)
|
write!(f, "{}", function)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,12 +14,18 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// 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/>.
|
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use crate::Span;
|
use crate::{InputKeyword, MutSelfKeyword, SelfKeyword, Span};
|
||||||
use leo_grammar::{
|
use leo_grammar::{
|
||||||
annotations::AnnotationArgument,
|
annotations::AnnotationArgument,
|
||||||
common::{Identifier as GrammarIdentifier, KeywordOrIdentifier, SelfKeyword, SelfKeywordOrIdentifier},
|
common::{
|
||||||
|
Identifier as GrammarIdentifier,
|
||||||
|
KeywordOrIdentifier,
|
||||||
|
MutSelfKeyword as GrammarMutSelfKeyword,
|
||||||
|
SelfKeyword as GrammarSelfKeyword,
|
||||||
|
SelfKeywordOrIdentifier,
|
||||||
|
},
|
||||||
expressions::CircuitName,
|
expressions::CircuitName,
|
||||||
functions::InputKeyword,
|
functions::InputKeyword as GrammarInputKeyword,
|
||||||
imports::PackageName as GrammarPackageName,
|
imports::PackageName as GrammarPackageName,
|
||||||
types::SelfType,
|
types::SelfType,
|
||||||
};
|
};
|
||||||
@ -128,20 +134,56 @@ impl<'ast> From<SelfKeywordOrIdentifier<'ast>> for Identifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ast> From<SelfKeyword<'ast>> for Identifier {
|
impl<'ast> From<GrammarSelfKeyword<'ast>> for Identifier {
|
||||||
fn from(self_: SelfKeyword<'ast>) -> Self {
|
fn from(grammar: GrammarSelfKeyword<'ast>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
name: self_.keyword,
|
name: grammar.keyword,
|
||||||
span: Span::from(self_.span),
|
span: Span::from(grammar.span),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ast> From<InputKeyword<'ast>> for Identifier {
|
impl From<SelfKeyword> for Identifier {
|
||||||
fn from(input: InputKeyword<'ast>) -> Self {
|
fn from(keyword: SelfKeyword) -> Self {
|
||||||
Self {
|
Self {
|
||||||
name: input.keyword,
|
name: keyword.to_string(),
|
||||||
span: Span::from(input.span),
|
span: keyword.span,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'ast> From<GrammarMutSelfKeyword<'ast>> for Identifier {
|
||||||
|
fn from(grammar: GrammarMutSelfKeyword<'ast>) -> Self {
|
||||||
|
Self {
|
||||||
|
name: grammar.to_string(),
|
||||||
|
span: Span::from(grammar.span),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<MutSelfKeyword> for Identifier {
|
||||||
|
fn from(keyword: MutSelfKeyword) -> Self {
|
||||||
|
Self {
|
||||||
|
name: keyword.to_string(),
|
||||||
|
span: keyword.span,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'ast> From<GrammarInputKeyword<'ast>> for Identifier {
|
||||||
|
fn from(grammar: GrammarInputKeyword<'ast>) -> Self {
|
||||||
|
Self {
|
||||||
|
name: grammar.keyword,
|
||||||
|
span: Span::from(grammar.span),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<InputKeyword> for Identifier {
|
||||||
|
fn from(keyword: InputKeyword) -> Self {
|
||||||
|
Self {
|
||||||
|
name: keyword.to_string(),
|
||||||
|
span: keyword.span,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
42
ast/src/common/input_keyword.rs
Normal file
42
ast/src/common/input_keyword.rs
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
// 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::Span;
|
||||||
|
use leo_grammar::functions::InputKeyword as GrammarInputKeyword;
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
/// The `input` keyword can view program register, record, and state values.
|
||||||
|
/// Values cannot be modified. The `input` keyword cannot be made mutable.
|
||||||
|
#[derive(Clone, Serialize, Deserialize)]
|
||||||
|
pub struct InputKeyword {
|
||||||
|
pub span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'ast> From<GrammarInputKeyword<'ast>> for InputKeyword {
|
||||||
|
fn from(grammar: GrammarInputKeyword<'ast>) -> Self {
|
||||||
|
Self {
|
||||||
|
span: Span::from(grammar.span),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for InputKeyword {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "input")
|
||||||
|
}
|
||||||
|
}
|
@ -26,12 +26,21 @@ pub use declare::*;
|
|||||||
pub mod identifier;
|
pub mod identifier;
|
||||||
pub use identifier::*;
|
pub use identifier::*;
|
||||||
|
|
||||||
|
pub mod input_keyword;
|
||||||
|
pub use input_keyword::*;
|
||||||
|
|
||||||
|
pub mod mut_self_keyword;
|
||||||
|
pub use mut_self_keyword::*;
|
||||||
|
|
||||||
pub mod positive_number;
|
pub mod positive_number;
|
||||||
pub use positive_number::*;
|
pub use positive_number::*;
|
||||||
|
|
||||||
pub mod range_or_expression;
|
pub mod range_or_expression;
|
||||||
pub use range_or_expression::*;
|
pub use range_or_expression::*;
|
||||||
|
|
||||||
|
pub mod self_keyword;
|
||||||
|
pub use self_keyword::*;
|
||||||
|
|
||||||
pub mod span;
|
pub mod span;
|
||||||
pub use span::*;
|
pub use span::*;
|
||||||
|
|
||||||
|
@ -14,14 +14,28 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// 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/>.
|
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use crate::{types::FunctionType, Attribute};
|
use crate::Span;
|
||||||
|
use leo_grammar::common::MutSelfKeyword as GrammarMutSelfKeyword;
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
/// The `mut self` keyword can view and modify circuit values inside of a circuit function.
|
||||||
pub struct CircuitFunctionType {
|
#[derive(Clone, Serialize, Deserialize)]
|
||||||
/// The function signature of the circuit function
|
pub struct MutSelfKeyword {
|
||||||
pub function: FunctionType,
|
pub span: Span,
|
||||||
/// The attributes of the circuit function
|
}
|
||||||
pub attribute: Option<Attribute>,
|
|
||||||
|
impl<'ast> From<GrammarMutSelfKeyword<'ast>> for MutSelfKeyword {
|
||||||
|
fn from(grammar: GrammarMutSelfKeyword<'ast>) -> Self {
|
||||||
|
Self {
|
||||||
|
span: Span::from(grammar.span),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for MutSelfKeyword {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "mut self")
|
||||||
|
}
|
||||||
}
|
}
|
42
ast/src/common/self_keyword.rs
Normal file
42
ast/src/common/self_keyword.rs
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
// 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::Span;
|
||||||
|
use leo_grammar::common::SelfKeyword as GrammarSelfKeyword;
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
/// The `self` keyword can view circuit values inside of a circuit function.
|
||||||
|
/// Circuit values cannot be modified. To modify values use the `mut self` [MutSelfKeyword].
|
||||||
|
#[derive(Clone, Serialize, Deserialize)]
|
||||||
|
pub struct SelfKeyword {
|
||||||
|
pub span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'ast> From<GrammarSelfKeyword<'ast>> for SelfKeyword {
|
||||||
|
fn from(grammar: GrammarSelfKeyword<'ast>) -> Self {
|
||||||
|
Self {
|
||||||
|
span: Span::from(grammar.span),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for SelfKeyword {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "self")
|
||||||
|
}
|
||||||
|
}
|
@ -60,6 +60,32 @@ impl Function {
|
|||||||
&self.identifier.name
|
&self.identifier.name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Returns `true` if the function has input `self` or `mut self`.
|
||||||
|
/// Returns `false` otherwise.
|
||||||
|
///
|
||||||
|
pub fn contains_self(&self) -> bool {
|
||||||
|
self.input.iter().any(|param| param.is_self())
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Returns `true` if the function has input `mut self`.
|
||||||
|
/// Returns `false` otherwise.
|
||||||
|
///
|
||||||
|
pub fn contains_mut_self(&self) -> bool {
|
||||||
|
self.input.iter().any(|param| param.is_mut_self())
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Returns a vector of [&FunctionInput] removing `self` and `mut self` inputs.
|
||||||
|
///
|
||||||
|
pub fn filter_self_inputs(&self) -> Vec<&FunctionInput> {
|
||||||
|
self.input
|
||||||
|
.iter()
|
||||||
|
.filter(|input| !input.is_self())
|
||||||
|
.collect::<Vec<&FunctionInput>>()
|
||||||
|
}
|
||||||
|
|
||||||
fn format(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn format(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, "function {}", self.identifier)?;
|
write!(f, "function {}", self.identifier)?;
|
||||||
|
|
||||||
|
@ -14,29 +14,27 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// 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/>.
|
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use crate::{FunctionInputVariable, Identifier, Span};
|
use crate::{FunctionInputVariable, InputKeyword, MutSelfKeyword, SelfKeyword};
|
||||||
use leo_grammar::functions::input::Input as GrammarInput;
|
use leo_grammar::functions::input::Input as GrammarInput;
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
|
/// Enumerates the possible inputs to a function.
|
||||||
|
#[derive(Clone, Serialize, Deserialize)]
|
||||||
pub enum FunctionInput {
|
pub enum FunctionInput {
|
||||||
InputKeyword(Identifier),
|
InputKeyword(InputKeyword),
|
||||||
|
SelfKeyword(SelfKeyword),
|
||||||
|
MutSelfKeyword(MutSelfKeyword),
|
||||||
Variable(FunctionInputVariable),
|
Variable(FunctionInputVariable),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ast> From<GrammarInput<'ast>> for FunctionInput {
|
impl<'ast> From<GrammarInput<'ast>> for FunctionInput {
|
||||||
fn from(input: GrammarInput<'ast>) -> Self {
|
fn from(input: GrammarInput<'ast>) -> Self {
|
||||||
match input {
|
match input {
|
||||||
GrammarInput::InputKeyword(input_keyword) => {
|
GrammarInput::InputKeyword(keyword) => FunctionInput::InputKeyword(InputKeyword::from(keyword)),
|
||||||
let id = Identifier {
|
GrammarInput::SelfKeyword(keyword) => FunctionInput::SelfKeyword(SelfKeyword::from(keyword)),
|
||||||
name: input_keyword.keyword,
|
GrammarInput::MutSelfKeyword(keyword) => FunctionInput::MutSelfKeyword(MutSelfKeyword::from(keyword)),
|
||||||
span: Span::from(input_keyword.span),
|
|
||||||
};
|
|
||||||
|
|
||||||
FunctionInput::InputKeyword(id)
|
|
||||||
}
|
|
||||||
GrammarInput::FunctionInput(function_input) => {
|
GrammarInput::FunctionInput(function_input) => {
|
||||||
FunctionInput::Variable(FunctionInputVariable::from(function_input))
|
FunctionInput::Variable(FunctionInputVariable::from(function_input))
|
||||||
}
|
}
|
||||||
@ -45,9 +43,37 @@ impl<'ast> From<GrammarInput<'ast>> for FunctionInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl FunctionInput {
|
impl FunctionInput {
|
||||||
|
///
|
||||||
|
/// Returns `true` if the function input is the `self` or `mut self` keyword.
|
||||||
|
/// Returns `false` otherwise.
|
||||||
|
///
|
||||||
|
pub fn is_self(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
FunctionInput::InputKeyword(_) => false,
|
||||||
|
FunctionInput::SelfKeyword(_) => true,
|
||||||
|
FunctionInput::MutSelfKeyword(_) => true,
|
||||||
|
FunctionInput::Variable(_) => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Returns `true` if the function input is the `mut self` keyword.
|
||||||
|
/// Returns `false` otherwise.
|
||||||
|
///
|
||||||
|
pub fn is_mut_self(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
FunctionInput::InputKeyword(_) => false,
|
||||||
|
FunctionInput::SelfKeyword(_) => false,
|
||||||
|
FunctionInput::MutSelfKeyword(_) => true,
|
||||||
|
FunctionInput::Variable(_) => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn format(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn format(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
FunctionInput::InputKeyword(id) => write!(f, "{}", id),
|
FunctionInput::InputKeyword(keyword) => write!(f, "{}", keyword),
|
||||||
|
FunctionInput::SelfKeyword(keyword) => write!(f, "{}", keyword),
|
||||||
|
FunctionInput::MutSelfKeyword(keyword) => write!(f, "{}", keyword),
|
||||||
FunctionInput::Variable(function_input) => write!(f, "{}", function_input),
|
FunctionInput::Variable(function_input) => write!(f, "{}", function_input),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -64,3 +90,18 @@ impl fmt::Debug for FunctionInput {
|
|||||||
self.format(f)
|
self.format(f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl PartialEq for FunctionInput {
|
||||||
|
/// Returns true if `self == other`. Does not compare spans.
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
match (self, other) {
|
||||||
|
(FunctionInput::InputKeyword(_), FunctionInput::InputKeyword(_)) => true,
|
||||||
|
(FunctionInput::SelfKeyword(_), FunctionInput::SelfKeyword(_)) => true,
|
||||||
|
(FunctionInput::MutSelfKeyword(_), FunctionInput::MutSelfKeyword(_)) => true,
|
||||||
|
(FunctionInput::Variable(left), FunctionInput::Variable(right)) => left.eq(right),
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eq for FunctionInput {}
|
||||||
|
@ -53,8 +53,8 @@ impl InputValue {
|
|||||||
Ok(InputValue::Boolean(boolean))
|
Ok(InputValue::Boolean(boolean))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_number(integer_type: IntegerType, number: String) -> Result<Self, InputParserError> {
|
fn from_number(integer_type: IntegerType, number: String) -> Self {
|
||||||
Ok(InputValue::Integer(integer_type, number))
|
InputValue::Integer(integer_type, number)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_group(group: InputGroupValue) -> Self {
|
fn from_group(group: InputGroupValue) -> Self {
|
||||||
@ -69,7 +69,7 @@ impl InputValue {
|
|||||||
match data_type {
|
match data_type {
|
||||||
DataType::Address(_) => Err(InputParserError::implicit_type(data_type, implicit)),
|
DataType::Address(_) => Err(InputParserError::implicit_type(data_type, implicit)),
|
||||||
DataType::Boolean(_) => Err(InputParserError::implicit_type(data_type, implicit)),
|
DataType::Boolean(_) => Err(InputParserError::implicit_type(data_type, implicit)),
|
||||||
DataType::Integer(integer_type) => InputValue::from_number(integer_type, implicit.to_string()),
|
DataType::Integer(integer_type) => Ok(InputValue::from_number(integer_type, implicit.to_string())),
|
||||||
DataType::Group(_) => Err(InputParserError::implicit_group(implicit)),
|
DataType::Group(_) => Err(InputParserError::implicit_group(implicit)),
|
||||||
DataType::Field(_) => Ok(InputValue::Field(implicit.to_string())),
|
DataType::Field(_) => Ok(InputValue::Field(implicit.to_string())),
|
||||||
}
|
}
|
||||||
@ -80,7 +80,7 @@ impl InputValue {
|
|||||||
(DataType::Address(_), Value::Address(address)) => Ok(InputValue::from_address_value(address)),
|
(DataType::Address(_), Value::Address(address)) => Ok(InputValue::from_address_value(address)),
|
||||||
(DataType::Boolean(_), Value::Boolean(boolean)) => InputValue::from_boolean(boolean),
|
(DataType::Boolean(_), Value::Boolean(boolean)) => InputValue::from_boolean(boolean),
|
||||||
(DataType::Integer(integer_type), Value::Integer(integer)) => {
|
(DataType::Integer(integer_type), Value::Integer(integer)) => {
|
||||||
InputValue::from_number(integer_type, integer.to_string())
|
Ok(InputValue::from_number(integer_type, integer.to_string()))
|
||||||
}
|
}
|
||||||
(DataType::Group(_), Value::Group(group)) => Ok(InputValue::from_group(group)),
|
(DataType::Group(_), Value::Group(group)) => Ok(InputValue::from_group(group)),
|
||||||
(DataType::Field(_), Value::Field(field)) => Ok(InputValue::from_field(field)),
|
(DataType::Field(_), Value::Field(field)) => Ok(InputValue::from_field(field)),
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "leo-compiler"
|
name = "leo-compiler"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
authors = [ "The Aleo Team <hello@aleo.org>" ]
|
authors = [ "The Aleo Team <hello@aleo.org>" ]
|
||||||
description = "Compiler of the Leo programming language"
|
description = "Compiler of the Leo programming language"
|
||||||
homepage = "https://aleo.org"
|
homepage = "https://aleo.org"
|
||||||
@ -19,43 +19,43 @@ edition = "2018"
|
|||||||
|
|
||||||
[dependencies.leo-ast]
|
[dependencies.leo-ast]
|
||||||
path = "../ast"
|
path = "../ast"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
|
|
||||||
[dependencies.leo-core]
|
[dependencies.leo-core]
|
||||||
path = "../core"
|
path = "../core"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
|
|
||||||
[dependencies.leo-gadgets]
|
[dependencies.leo-gadgets]
|
||||||
path = "../gadgets"
|
path = "../gadgets"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
|
|
||||||
[dependencies.leo-grammar]
|
[dependencies.leo-grammar]
|
||||||
path = "../grammar"
|
path = "../grammar"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
|
|
||||||
[dependencies.leo-imports]
|
[dependencies.leo-imports]
|
||||||
path = "../imports"
|
path = "../imports"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
|
|
||||||
[dependencies.leo-input]
|
[dependencies.leo-input]
|
||||||
path = "../input"
|
path = "../input"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
|
|
||||||
[dependencies.leo-package]
|
[dependencies.leo-package]
|
||||||
path = "../package"
|
path = "../package"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
|
|
||||||
[dependencies.leo-state]
|
[dependencies.leo-state]
|
||||||
path = "../state"
|
path = "../state"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
|
|
||||||
[dependencies.leo-symbol-table]
|
[dependencies.leo-symbol-table]
|
||||||
path = "../symbol-table"
|
path = "../symbol-table"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
|
|
||||||
[dependencies.leo-type-inference]
|
[dependencies.leo-type-inference]
|
||||||
path = "../type-inference"
|
path = "../type-inference"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
|
|
||||||
[dependencies.snarkos-curves]
|
[dependencies.snarkos-curves]
|
||||||
version = "1.1.3"
|
version = "1.1.3"
|
||||||
|
@ -206,7 +206,7 @@ impl ExpressionError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn undefined_identifier(identifier: Identifier) -> Self {
|
pub fn undefined_identifier(identifier: Identifier) -> Self {
|
||||||
let message = format!("cannot find value `{}` in this scope", identifier.name);
|
let message = format!("Cannot find value `{}` in this scope", identifier.name);
|
||||||
|
|
||||||
Self::new_from_span(message, identifier.span)
|
Self::new_from_span(message, identifier.span)
|
||||||
}
|
}
|
||||||
|
@ -82,12 +82,6 @@ impl FunctionError {
|
|||||||
FunctionError::Error(FormattedError::new_from_span(message, span))
|
FunctionError::Error(FormattedError::new_from_span(message, span))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn arguments_length(expected: usize, actual: usize, span: Span) -> Self {
|
|
||||||
let message = format!("function expected {} input variables, found {}", expected, actual);
|
|
||||||
|
|
||||||
Self::new_from_span(message, span)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn invalid_array(actual: String, span: Span) -> Self {
|
pub fn invalid_array(actual: String, span: Span) -> Self {
|
||||||
let message = format!("Expected function input array, found `{}`", actual);
|
let message = format!("Expected function input array, found `{}`", actual);
|
||||||
|
|
||||||
|
@ -67,7 +67,9 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
match matched_member {
|
match matched_member {
|
||||||
Some(member) => {
|
Some(member) => {
|
||||||
match &member.1 {
|
match &member.1 {
|
||||||
ConstrainedValue::Function(ref _circuit_identifier, ref _function) => {
|
ConstrainedValue::Function(ref _circuit_identifier, ref function) => {
|
||||||
|
// Check for function input `self` or `mut self`.
|
||||||
|
if function.contains_self() {
|
||||||
// Pass circuit members into function call by value
|
// Pass circuit members into function call by value
|
||||||
for stored_member in members {
|
for stored_member in members {
|
||||||
let circuit_scope = new_scope(&file_scope, &circuit_name.name);
|
let circuit_scope = new_scope(&file_scope, &circuit_name.name);
|
||||||
@ -77,6 +79,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
self.store(variable, stored_member.1.clone());
|
self.store(variable, stored_member.1.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
ConstrainedValue::Static(value) => {
|
ConstrainedValue::Static(value) => {
|
||||||
return Err(ExpressionError::invalid_static_access(value.to_string(), span));
|
return Err(ExpressionError::invalid_static_access(value.to_string(), span));
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
|
|
||||||
for member in circuit.members.into_iter() {
|
for member in circuit.members.into_iter() {
|
||||||
match member {
|
match member {
|
||||||
CircuitMember::CircuitVariable(is_mutable, identifier, type_) => {
|
CircuitMember::CircuitVariable(identifier, type_) => {
|
||||||
let matched_variable = members
|
let matched_variable = members
|
||||||
.clone()
|
.clone()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@ -66,7 +66,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
match matched_variable {
|
match matched_variable {
|
||||||
Some(variable) => {
|
Some(variable) => {
|
||||||
// Resolve and enforce circuit variable
|
// Resolve and enforce circuit variable
|
||||||
let mut variable_value = self.enforce_expression(
|
let variable_value = self.enforce_expression(
|
||||||
cs,
|
cs,
|
||||||
file_scope,
|
file_scope,
|
||||||
function_scope,
|
function_scope,
|
||||||
@ -74,25 +74,16 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
variable.expression,
|
variable.expression,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// Add mutability to circuit variable
|
|
||||||
if is_mutable {
|
|
||||||
variable_value = ConstrainedValue::Mutable(Box::new(variable_value))
|
|
||||||
}
|
|
||||||
|
|
||||||
resolved_members.push(ConstrainedCircuitMember(identifier, variable_value))
|
resolved_members.push(ConstrainedCircuitMember(identifier, variable_value))
|
||||||
}
|
}
|
||||||
None => return Err(ExpressionError::expected_circuit_member(identifier.to_string(), span)),
|
None => return Err(ExpressionError::expected_circuit_member(identifier.to_string(), span)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CircuitMember::CircuitFunction(_static, function) => {
|
CircuitMember::CircuitFunction(function) => {
|
||||||
let identifier = function.identifier.clone();
|
let identifier = function.identifier.clone();
|
||||||
let mut constrained_function_value =
|
let constrained_function_value =
|
||||||
ConstrainedValue::Function(Some(circuit_identifier.clone()), function);
|
ConstrainedValue::Function(Some(circuit_identifier.clone()), function);
|
||||||
|
|
||||||
if _static {
|
|
||||||
constrained_function_value = ConstrainedValue::Static(Box::new(constrained_function_value));
|
|
||||||
}
|
|
||||||
|
|
||||||
resolved_members.push(ConstrainedCircuitMember(identifier, constrained_function_value));
|
resolved_members.push(ConstrainedCircuitMember(identifier, constrained_function_value));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -56,22 +56,13 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
|
|
||||||
// Find static circuit function
|
// Find static circuit function
|
||||||
let matched_function = circuit.members.into_iter().find(|member| match member {
|
let matched_function = circuit.members.into_iter().find(|member| match member {
|
||||||
CircuitMember::CircuitFunction(_static, function) => function.identifier == circuit_member,
|
CircuitMember::CircuitFunction(function) => function.identifier == circuit_member,
|
||||||
_ => false,
|
_ => false,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Return errors if no static function exists
|
// Return errors if no static function exists
|
||||||
let function = match matched_function {
|
let function = match matched_function {
|
||||||
Some(CircuitMember::CircuitFunction(_static, function)) => {
|
Some(CircuitMember::CircuitFunction(function)) => function,
|
||||||
if _static {
|
|
||||||
function
|
|
||||||
} else {
|
|
||||||
return Err(ExpressionError::invalid_member_access(
|
|
||||||
function.identifier.to_string(),
|
|
||||||
span,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
_ => {
|
||||||
return Err(ExpressionError::undefined_member_access(
|
return Err(ExpressionError::undefined_member_access(
|
||||||
circuit.circuit_name.to_string(),
|
circuit.circuit_name.to_string(),
|
||||||
|
@ -23,22 +23,13 @@ use crate::{
|
|||||||
GroupType,
|
GroupType,
|
||||||
};
|
};
|
||||||
|
|
||||||
use leo_ast::{Expression, Function, FunctionInput, Span};
|
use leo_ast::{Expression, Function, FunctionInput};
|
||||||
|
|
||||||
use snarkos_models::{
|
use snarkos_models::{
|
||||||
curves::{Field, PrimeField},
|
curves::{Field, PrimeField},
|
||||||
gadgets::{r1cs::ConstraintSystem, utilities::boolean::Boolean},
|
gadgets::{r1cs::ConstraintSystem, utilities::boolean::Boolean},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn check_arguments_length(expected: usize, actual: usize, span: &Span) -> Result<(), FunctionError> {
|
|
||||||
// Make sure we are given the correct number of arguments
|
|
||||||
if expected != actual {
|
|
||||||
Err(FunctionError::arguments_length(expected, actual, span.to_owned()))
|
|
||||||
} else {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||||
pub(crate) fn enforce_function<CS: ConstraintSystem<F>>(
|
pub(crate) fn enforce_function<CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -51,17 +42,29 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
) -> Result<ConstrainedValue<F, G>, FunctionError> {
|
) -> Result<ConstrainedValue<F, G>, FunctionError> {
|
||||||
let function_name = new_scope(scope, function.get_name());
|
let function_name = new_scope(scope, function.get_name());
|
||||||
|
|
||||||
// Make sure we are given the correct number of input variables
|
// Store if function contains input `mut self`.
|
||||||
check_arguments_length(function.input.len(), input.len(), &function.span)?;
|
let mut_self = function.contains_mut_self();
|
||||||
|
|
||||||
// Store input values as new variables in resolved program
|
// Store input values as new variables in resolved program
|
||||||
for (input_model, input_expression) in function.input.iter().zip(input.into_iter()) {
|
for (input_model, input_expression) in function.filter_self_inputs().iter().zip(input.into_iter()) {
|
||||||
let (name, value) = match input_model {
|
let (name, value) = match input_model {
|
||||||
FunctionInput::InputKeyword(identifier) => {
|
FunctionInput::InputKeyword(keyword) => {
|
||||||
let input_value =
|
let value =
|
||||||
self.enforce_function_input(cs, scope, caller_scope, &function_name, None, input_expression)?;
|
self.enforce_function_input(cs, scope, caller_scope, &function_name, None, input_expression)?;
|
||||||
|
|
||||||
(&identifier.name, input_value)
|
(keyword.to_string(), value)
|
||||||
|
}
|
||||||
|
FunctionInput::SelfKeyword(keyword) => {
|
||||||
|
let value =
|
||||||
|
self.enforce_function_input(cs, scope, caller_scope, &function_name, None, input_expression)?;
|
||||||
|
|
||||||
|
(keyword.to_string(), value)
|
||||||
|
}
|
||||||
|
FunctionInput::MutSelfKeyword(keyword) => {
|
||||||
|
let value =
|
||||||
|
self.enforce_function_input(cs, scope, caller_scope, &function_name, None, input_expression)?;
|
||||||
|
|
||||||
|
(keyword.to_string(), value)
|
||||||
}
|
}
|
||||||
FunctionInput::Variable(input_model) => {
|
FunctionInput::Variable(input_model) => {
|
||||||
// First evaluate input expression
|
// First evaluate input expression
|
||||||
@ -78,7 +81,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
input_value = ConstrainedValue::Mutable(Box::new(input_value))
|
input_value = ConstrainedValue::Mutable(Box::new(input_value))
|
||||||
}
|
}
|
||||||
|
|
||||||
(&input_model.identifier.name, input_value)
|
(input_model.identifier.name.clone(), input_value)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -100,6 +103,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
statement.clone(),
|
statement.clone(),
|
||||||
function.output.clone(),
|
function.output.clone(),
|
||||||
declared_circuit_reference,
|
declared_circuit_reference,
|
||||||
|
mut_self,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
results.append(&mut result);
|
results.append(&mut result);
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use crate::{errors::FunctionError, ConstrainedCircuitMember, ConstrainedProgram, ConstrainedValue, GroupType};
|
use crate::{errors::FunctionError, ConstrainedCircuitMember, ConstrainedProgram, ConstrainedValue, GroupType};
|
||||||
use leo_ast::{Identifier, Input};
|
use leo_ast::{Identifier, Input, InputKeyword};
|
||||||
|
|
||||||
use snarkos_models::{
|
use snarkos_models::{
|
||||||
curves::{Field, PrimeField},
|
curves::{Field, PrimeField},
|
||||||
@ -31,26 +31,26 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
pub fn allocate_input_keyword<CS: ConstraintSystem<F>>(
|
pub fn allocate_input_keyword<CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
identifier: Identifier,
|
keyword: InputKeyword,
|
||||||
input: &Input,
|
input: &Input,
|
||||||
) -> Result<ConstrainedValue<F, G>, FunctionError> {
|
) -> Result<ConstrainedValue<F, G>, FunctionError> {
|
||||||
// Create an identifier for each input variable
|
// Create an identifier for each input variable
|
||||||
|
|
||||||
let registers_name = Identifier {
|
let registers_name = Identifier {
|
||||||
name: REGISTERS_VARIABLE_NAME.to_string(),
|
name: REGISTERS_VARIABLE_NAME.to_string(),
|
||||||
span: identifier.span.clone(),
|
span: keyword.span.clone(),
|
||||||
};
|
};
|
||||||
let record_name = Identifier {
|
let record_name = Identifier {
|
||||||
name: RECORD_VARIABLE_NAME.to_string(),
|
name: RECORD_VARIABLE_NAME.to_string(),
|
||||||
span: identifier.span.clone(),
|
span: keyword.span.clone(),
|
||||||
};
|
};
|
||||||
let state_name = Identifier {
|
let state_name = Identifier {
|
||||||
name: STATE_VARIABLE_NAME.to_string(),
|
name: STATE_VARIABLE_NAME.to_string(),
|
||||||
span: identifier.span.clone(),
|
span: keyword.span.clone(),
|
||||||
};
|
};
|
||||||
let state_leaf_name = Identifier {
|
let state_leaf_name = Identifier {
|
||||||
name: STATE_LEAF_VARIABLE_NAME.to_string(),
|
name: STATE_LEAF_VARIABLE_NAME.to_string(),
|
||||||
span: identifier.span.clone(),
|
span: keyword.span.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Fetch each input variable's definitions
|
// Fetch each input variable's definitions
|
||||||
@ -82,6 +82,6 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
|
|
||||||
// Return input variable keyword as circuit expression
|
// Return input variable keyword as circuit expression
|
||||||
|
|
||||||
Ok(ConstrainedValue::CircuitExpression(identifier, members))
|
Ok(ConstrainedValue::CircuitExpression(Identifier::from(keyword), members))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ use crate::{
|
|||||||
OutputBytes,
|
OutputBytes,
|
||||||
};
|
};
|
||||||
|
|
||||||
use leo_ast::{Expression, Function, FunctionInput, Input};
|
use leo_ast::{Expression, Function, FunctionInput, Identifier, Input};
|
||||||
|
|
||||||
use snarkos_models::{
|
use snarkos_models::{
|
||||||
curves::{Field, PrimeField},
|
curves::{Field, PrimeField},
|
||||||
@ -44,11 +44,16 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
// Iterate over main function input variables and allocate new values
|
// Iterate over main function input variables and allocate new values
|
||||||
let mut input_variables = Vec::with_capacity(function.input.len());
|
let mut input_variables = Vec::with_capacity(function.input.len());
|
||||||
for input_model in function.input.clone().into_iter() {
|
for input_model in function.input.clone().into_iter() {
|
||||||
let (identifier, value) = match input_model {
|
let (input_id, value) = match input_model {
|
||||||
FunctionInput::InputKeyword(identifier) => {
|
FunctionInput::InputKeyword(keyword) => {
|
||||||
let value = self.allocate_input_keyword(cs, identifier.clone(), &input)?;
|
let input_id = Identifier::new_with_span(&keyword.to_string(), &keyword.span);
|
||||||
|
let value = self.allocate_input_keyword(cs, keyword, &input)?;
|
||||||
|
|
||||||
(identifier, value)
|
(input_id, value)
|
||||||
|
}
|
||||||
|
FunctionInput::SelfKeyword(_) => unimplemented!("cannot access self keyword in main function"),
|
||||||
|
FunctionInput::MutSelfKeyword(_) => {
|
||||||
|
unimplemented!("cannot access mut self keyword in main function")
|
||||||
}
|
}
|
||||||
FunctionInput::Variable(input_model) => {
|
FunctionInput::Variable(input_model) => {
|
||||||
let name = input_model.identifier.name.clone();
|
let name = input_model.identifier.name.clone();
|
||||||
@ -63,12 +68,12 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Store input as variable with {function_name}_{identifier_name}
|
// Store input as variable with {function_name}_{identifier_name}
|
||||||
let input_name = new_scope(&function_name, &identifier.name);
|
let input_name = new_scope(&function_name, &input_id.to_string());
|
||||||
|
|
||||||
// Store a new variable for every allocated main function input
|
// Store a new variable for every allocated main function input
|
||||||
self.store(input_name, value);
|
self.store(input_name, value);
|
||||||
|
|
||||||
input_variables.push(Expression::Identifier(identifier));
|
input_variables.push(Expression::Identifier(input_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
let span = function.span.clone();
|
let span = function.span.clone();
|
||||||
|
@ -43,6 +43,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
function_scope: &str,
|
function_scope: &str,
|
||||||
declared_circuit_reference: &str,
|
declared_circuit_reference: &str,
|
||||||
indicator: &Boolean,
|
indicator: &Boolean,
|
||||||
|
mut_self: bool,
|
||||||
assignee: Assignee,
|
assignee: Assignee,
|
||||||
expression: Expression,
|
expression: Expression,
|
||||||
span: &Span,
|
span: &Span,
|
||||||
@ -87,7 +88,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
}
|
}
|
||||||
AssigneeAccess::Member(identifier) => {
|
AssigneeAccess::Member(identifier) => {
|
||||||
// Mutate a circuit variable using the self keyword.
|
// Mutate a circuit variable using the self keyword.
|
||||||
if assignee.identifier.is_self() {
|
if assignee.identifier.is_self() && mut_self {
|
||||||
let self_circuit_variable_name = new_scope(&assignee.identifier.name, &identifier.name);
|
let self_circuit_variable_name = new_scope(&assignee.identifier.name, &identifier.name);
|
||||||
let self_variable_name = new_scope(file_scope, &self_circuit_variable_name);
|
let self_variable_name = new_scope(file_scope, &self_circuit_variable_name);
|
||||||
let value = self.mutate_circuit_variable(
|
let value = self.mutate_circuit_variable(
|
||||||
|
@ -59,9 +59,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
span.to_owned(),
|
span.to_owned(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
ConstrainedValue::Mutable(value) => {
|
value => {
|
||||||
// Mutate the circuit variable's value in place
|
|
||||||
|
|
||||||
// Check that the new value type == old value type
|
// Check that the new value type == old value type
|
||||||
new_value.resolve_type(Some(value.to_type(span)?), span)?;
|
new_value.resolve_type(Some(value.to_type(span)?), span)?;
|
||||||
|
|
||||||
@ -87,13 +85,6 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
|
|
||||||
Ok(selected_value)
|
Ok(selected_value)
|
||||||
}
|
}
|
||||||
_ => {
|
|
||||||
// Throw an error if we try to mutate an immutable circuit variable
|
|
||||||
Err(StatementError::immutable_circuit_variable(
|
|
||||||
variable_name.name,
|
|
||||||
span.to_owned(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
// Throw an error if the circuit variable does not exist in the circuit
|
// Throw an error if the circuit variable does not exist in the circuit
|
||||||
|
@ -25,6 +25,9 @@ use snarkos_models::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||||
|
/// Evaluates a branch of one or more statements and returns a result in
|
||||||
|
/// the given scope.
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn evaluate_branch<CS: ConstraintSystem<F>>(
|
pub fn evaluate_branch<CS: ConstraintSystem<F>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
cs: &mut CS,
|
cs: &mut CS,
|
||||||
@ -33,6 +36,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
indicator: &Boolean,
|
indicator: &Boolean,
|
||||||
statements: Vec<Statement>,
|
statements: Vec<Statement>,
|
||||||
return_type: Option<Type>,
|
return_type: Option<Type>,
|
||||||
|
mut_self: bool,
|
||||||
) -> StatementResult<Vec<IndicatorAndConstrainedValue<F, G>>> {
|
) -> StatementResult<Vec<IndicatorAndConstrainedValue<F, G>>> {
|
||||||
let mut results = Vec::with_capacity(statements.len());
|
let mut results = Vec::with_capacity(statements.len());
|
||||||
// Evaluate statements. Only allow a single return argument to be returned.
|
// Evaluate statements. Only allow a single return argument to be returned.
|
||||||
@ -45,6 +49,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
statement,
|
statement,
|
||||||
return_type.clone(),
|
return_type.clone(),
|
||||||
"",
|
"",
|
||||||
|
mut_self,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
results.append(&mut value);
|
results.append(&mut value);
|
||||||
|
@ -52,6 +52,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
indicator: &Boolean,
|
indicator: &Boolean,
|
||||||
statement: ConditionalStatement,
|
statement: ConditionalStatement,
|
||||||
return_type: Option<Type>,
|
return_type: Option<Type>,
|
||||||
|
mut_self: bool,
|
||||||
span: &Span,
|
span: &Span,
|
||||||
) -> StatementResult<Vec<IndicatorAndConstrainedValue<F, G>>> {
|
) -> StatementResult<Vec<IndicatorAndConstrainedValue<F, G>>> {
|
||||||
let statement_string = statement.to_string();
|
let statement_string = statement.to_string();
|
||||||
@ -95,6 +96,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
&branch_1_indicator,
|
&branch_1_indicator,
|
||||||
statement.statements,
|
statement.statements,
|
||||||
return_type.clone(),
|
return_type.clone(),
|
||||||
|
mut_self,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
results.append(&mut branch_1_result);
|
results.append(&mut branch_1_result);
|
||||||
@ -123,6 +125,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
&branch_2_indicator,
|
&branch_2_indicator,
|
||||||
*nested,
|
*nested,
|
||||||
return_type,
|
return_type,
|
||||||
|
mut_self,
|
||||||
span,
|
span,
|
||||||
)?,
|
)?,
|
||||||
ConditionalNestedOrEndStatement::End(statements) => self.evaluate_branch(
|
ConditionalNestedOrEndStatement::End(statements) => self.evaluate_branch(
|
||||||
@ -132,6 +135,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
&branch_2_indicator,
|
&branch_2_indicator,
|
||||||
statements,
|
statements,
|
||||||
return_type,
|
return_type,
|
||||||
|
mut_self,
|
||||||
)?,
|
)?,
|
||||||
},
|
},
|
||||||
None => vec![],
|
None => vec![],
|
||||||
|
@ -48,6 +48,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
stop: Expression,
|
stop: Expression,
|
||||||
statements: Vec<Statement>,
|
statements: Vec<Statement>,
|
||||||
return_type: Option<Type>,
|
return_type: Option<Type>,
|
||||||
|
mut_self: bool,
|
||||||
span: &Span,
|
span: &Span,
|
||||||
) -> StatementResult<Vec<IndicatorAndConstrainedValue<F, G>>> {
|
) -> StatementResult<Vec<IndicatorAndConstrainedValue<F, G>>> {
|
||||||
let mut results = vec![];
|
let mut results = vec![];
|
||||||
@ -74,6 +75,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
indicator,
|
indicator,
|
||||||
statements.clone(),
|
statements.clone(),
|
||||||
return_type.clone(),
|
return_type.clone(),
|
||||||
|
mut_self,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
results.append(&mut result);
|
results.append(&mut result);
|
||||||
|
@ -45,6 +45,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
statement: Statement,
|
statement: Statement,
|
||||||
return_type: Option<Type>,
|
return_type: Option<Type>,
|
||||||
declared_circuit_reference: &str,
|
declared_circuit_reference: &str,
|
||||||
|
mut_self: bool,
|
||||||
) -> StatementResult<Vec<IndicatorAndConstrainedValue<F, G>>> {
|
) -> StatementResult<Vec<IndicatorAndConstrainedValue<F, G>>> {
|
||||||
let mut results = vec![];
|
let mut results = vec![];
|
||||||
|
|
||||||
@ -75,6 +76,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
function_scope,
|
function_scope,
|
||||||
declared_circuit_reference,
|
declared_circuit_reference,
|
||||||
indicator,
|
indicator,
|
||||||
|
mut_self,
|
||||||
variable,
|
variable,
|
||||||
expression,
|
expression,
|
||||||
&span,
|
&span,
|
||||||
@ -88,6 +90,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
indicator,
|
indicator,
|
||||||
statement,
|
statement,
|
||||||
return_type,
|
return_type,
|
||||||
|
mut_self,
|
||||||
&span,
|
&span,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
@ -104,6 +107,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
|||||||
start_stop.1,
|
start_stop.1,
|
||||||
statements,
|
statements,
|
||||||
return_type,
|
return_type,
|
||||||
|
mut_self,
|
||||||
&span,
|
&span,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ circuit Foo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
circuit Bar {
|
circuit Bar {
|
||||||
static function bar() {
|
function bar() {
|
||||||
let f = Foo { a: 0u32 };
|
let f = Foo { a: 0u32 };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
circuit Foo {
|
circuit Foo {
|
||||||
static function echo(x: u32) -> u32 {
|
function echo(x: u32) -> u32 {
|
||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
circuit Foo {
|
circuit Foo {
|
||||||
x: u32,
|
x: u32,
|
||||||
|
|
||||||
function add_x(y: u32) -> u32 {
|
function add_x(self, y: u32) -> u32 {
|
||||||
return self.x + y
|
return self.x + y
|
||||||
}
|
}
|
||||||
|
|
||||||
function call_add_x(y: u32) -> u32 {
|
function call_add_x(self, y: u32) -> u32 {
|
||||||
return self.add_x(y)
|
return self.add_x(y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function main() {
|
function main() {
|
||||||
let a = Foo { x: 1u32 };
|
let a = Foo { x: 1u32 };
|
||||||
let b = a.call_add_x(1u32);
|
let b = a.add_x(1u32);
|
||||||
|
|
||||||
console.assert(b == 2u32);
|
console.assert(b == 2u32);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
circuit Foo {
|
circuit Foo {
|
||||||
static function echo(x: u32) -> u32 {
|
function echo(x: u32) -> u32 {
|
||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,5 +5,5 @@ circuit Foo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function main() {
|
function main() {
|
||||||
let err = Foo::echo(1u32); // echo is a non-static function and must be accessed using `.`
|
let err = Foo::echo(1u32); // Correct, echo is a static function and must be accessed using `::`
|
||||||
}
|
}
|
@ -1,11 +1,11 @@
|
|||||||
circuit Foo {
|
circuit Foo {
|
||||||
static function qux() {}
|
function qux() {}
|
||||||
|
|
||||||
static function bar() {
|
function bar() {
|
||||||
Self::qux();
|
Self::qux();
|
||||||
}
|
}
|
||||||
|
|
||||||
static function baz() {
|
function baz() {
|
||||||
Self::bar();
|
Self::bar();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
circuit Foo {
|
circuit Foo {
|
||||||
static function echo(x: u32) -> u32 {
|
function echo(x: u32) -> u32 {
|
||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
circuit Foo {
|
circuit Foo {
|
||||||
foo: u32,
|
foo: u32,
|
||||||
|
|
||||||
static function bar() -> u32 {
|
function bar() -> u32 {
|
||||||
return 1u32
|
return 1u32
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -119,9 +119,9 @@ fn test_member_static_function_nested() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_member_static_function_invalid() {
|
fn test_member_static_function_invalid() {
|
||||||
let bytes = include_bytes!("member_static_function_invalid.leo");
|
let bytes = include_bytes!("member_static_function_invalid.leo");
|
||||||
let error = parse_program(bytes).err().unwrap();
|
let program = parse_program(bytes).unwrap();
|
||||||
|
|
||||||
expect_type_inference_error(error)
|
assert_satisfied(program)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -219,9 +219,9 @@ fn test_self_member_pass() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_self_member_invalid() {
|
fn test_self_member_invalid() {
|
||||||
let bytes = include_bytes!("self_member_invalid.leo");
|
let bytes = include_bytes!("self_member_invalid.leo");
|
||||||
let program = parse_program(bytes).unwrap();
|
let error = parse_program(bytes).err().unwrap();
|
||||||
|
|
||||||
let _err = expect_compiler_error(program);
|
expect_type_inference_error(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -3,7 +3,7 @@ circuit Foo {
|
|||||||
|
|
||||||
function bar() {}
|
function bar() {}
|
||||||
|
|
||||||
function set_a(new: u8) {
|
function set_a(mut self, new: u8) {
|
||||||
self.bar = new;
|
self.bar = new;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
circuit Foo {
|
circuit Foo {
|
||||||
a: u8,
|
a: u8,
|
||||||
|
|
||||||
static function bar() {}
|
function bar() {}
|
||||||
|
|
||||||
function set_a(new: u8) {
|
function set_a(mut self, new: u8) {
|
||||||
self.bar = new;
|
self.bar = new;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
circuit Foo {
|
circuit Foo {
|
||||||
mut a: u8,
|
a: u8,
|
||||||
|
|
||||||
function set_a(new: u8) {
|
function set_a(mut self, new: u8) {
|
||||||
self.a = new;
|
self.a = new;
|
||||||
console.assert(self.a == new);
|
console.assert(self.a == new);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
circuit Foo {
|
circuit Foo {
|
||||||
a: u8,
|
a: u8,
|
||||||
|
|
||||||
function set_a(new: u8) {
|
function set_a(self, new: u8) {
|
||||||
self.a = new;
|
self.a = new;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
circuit Foo {
|
circuit Foo {
|
||||||
static function bar() {}
|
function bar() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
function main() {
|
function main() {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
circuit Foo {
|
circuit Foo {
|
||||||
mut a: u8,
|
a: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
function main() {
|
function main() {
|
||||||
|
@ -3,7 +3,7 @@ circuit Foo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function main() {
|
function main() {
|
||||||
let mut f = Foo { a: 0u8 };
|
let f = Foo { a: 0u8 };
|
||||||
|
|
||||||
f.a = 1u8;
|
f.a = 1u8;
|
||||||
}
|
}
|
@ -1,11 +1,11 @@
|
|||||||
circuit PedersenHash {
|
circuit PedersenHash {
|
||||||
parameters: [u32; 512]
|
parameters: [u32; 512]
|
||||||
|
|
||||||
static function new(parameters: [u32; 512]) -> Self {
|
function new(parameters: [u32; 512]) -> Self {
|
||||||
return Self { parameters: parameters }
|
return Self { parameters: parameters }
|
||||||
}
|
}
|
||||||
|
|
||||||
function hash(bits: [bool; 512]) -> u32 {
|
function hash(self, bits: [bool; 512]) -> u32 {
|
||||||
let mut digest: u32 = 0;
|
let mut digest: u32 = 0;
|
||||||
for i in 0..512 {
|
for i in 0..512 {
|
||||||
let base = if bits[i] ? self.parameters[i] : 0u32;
|
let base = if bits[i] ? self.parameters[i] : 0u32;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
circuit Foo {
|
circuit Foo {
|
||||||
f: u32,
|
f: u32,
|
||||||
|
|
||||||
function bar() -> u32 {
|
function bar(self) -> u32 {
|
||||||
return self.f
|
return self.f
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// Adding the `mut` keyword makes a circuit variable mutable.
|
// Adding the `mut` keyword makes a circuit variable mutable.
|
||||||
circuit Foo {
|
circuit Foo {
|
||||||
static function bar() {}
|
function bar() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
function main() {
|
function main() {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// Adding the `mut` keyword makes a circuit variable mutable.
|
// Adding the `mut` keyword makes a circuit variable mutable.
|
||||||
circuit Foo {
|
circuit Foo {
|
||||||
mut x: u32
|
x: u32
|
||||||
}
|
}
|
||||||
|
|
||||||
function main() {
|
function main() {
|
||||||
|
@ -78,7 +78,7 @@ fn test_circuit_mut() {
|
|||||||
let bytes = include_bytes!("circuit_mut.leo");
|
let bytes = include_bytes!("circuit_mut.leo");
|
||||||
let program = parse_program(bytes).unwrap();
|
let program = parse_program(bytes).unwrap();
|
||||||
|
|
||||||
expect_compiler_error(program);
|
assert_satisfied(program);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -53,7 +53,7 @@ fn test_undefined() {
|
|||||||
" 2 | return a",
|
" 2 | return a",
|
||||||
" | ^",
|
" | ^",
|
||||||
" |",
|
" |",
|
||||||
" = cannot find value `a` in this scope",
|
" = Cannot find value `a` in this scope",
|
||||||
]
|
]
|
||||||
.join("\n")
|
.join("\n")
|
||||||
);
|
);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "leo-core"
|
name = "leo-core"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
authors = [ "The Aleo Team <hello@aleo.org>" ]
|
authors = [ "The Aleo Team <hello@aleo.org>" ]
|
||||||
description = "Core package dependencies of the Leo programming language"
|
description = "Core package dependencies of the Leo programming language"
|
||||||
homepage = "https://aleo.org"
|
homepage = "https://aleo.org"
|
||||||
@ -19,11 +19,11 @@ edition = "2018"
|
|||||||
|
|
||||||
[dependencies.leo-ast]
|
[dependencies.leo-ast]
|
||||||
path = "../ast"
|
path = "../ast"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
|
|
||||||
[dependencies.leo-gadgets]
|
[dependencies.leo-gadgets]
|
||||||
path = "../gadgets"
|
path = "../gadgets"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
|
|
||||||
[dependencies.snarkos-errors]
|
[dependencies.snarkos-errors]
|
||||||
version = "1.1.3"
|
version = "1.1.3"
|
||||||
|
@ -61,9 +61,7 @@ impl CoreCircuit for Blake2sCircuit {
|
|||||||
fn ast(circuit_name: Identifier, span: Span) -> Circuit {
|
fn ast(circuit_name: Identifier, span: Span) -> Circuit {
|
||||||
Circuit {
|
Circuit {
|
||||||
circuit_name,
|
circuit_name,
|
||||||
members: vec![CircuitMember::CircuitFunction(
|
members: vec![CircuitMember::CircuitFunction(Function {
|
||||||
true, // static function
|
|
||||||
Function {
|
|
||||||
identifier: Identifier {
|
identifier: Identifier {
|
||||||
name: "hash".to_owned(),
|
name: "hash".to_owned(),
|
||||||
span: span.clone(),
|
span: span.clone(),
|
||||||
@ -125,8 +123,7 @@ impl CoreCircuit for Blake2sCircuit {
|
|||||||
span.clone(),
|
span.clone(),
|
||||||
)],
|
)],
|
||||||
span,
|
span,
|
||||||
},
|
})],
|
||||||
)],
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "leo-gadgets"
|
name = "leo-gadgets"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
authors = [ "The Aleo Team <hello@aleo.org>" ]
|
authors = [ "The Aleo Team <hello@aleo.org>" ]
|
||||||
description = "Gadgets of the Leo programming language"
|
description = "Gadgets of the Leo programming language"
|
||||||
homepage = "https://aleo.org"
|
homepage = "https://aleo.org"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "leo-grammar"
|
name = "leo-grammar"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
authors = [ "The Aleo Team <hello@aleo.org>" ]
|
authors = [ "The Aleo Team <hello@aleo.org>" ]
|
||||||
description = "AST generated by pest from the Leo grammar rules"
|
description = "AST generated by pest from the Leo grammar rules"
|
||||||
homepage = "https://aleo.org"
|
homepage = "https://aleo.org"
|
||||||
|
@ -14,10 +14,7 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// 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/>.
|
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use crate::{
|
use crate::{ast::Rule, circuits::CircuitVariableDefinition, functions::Function};
|
||||||
ast::Rule,
|
|
||||||
circuits::{CircuitFunction, CircuitVariableDefinition},
|
|
||||||
};
|
|
||||||
|
|
||||||
use pest_ast::FromPest;
|
use pest_ast::FromPest;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
@ -26,5 +23,5 @@ use serde::Serialize;
|
|||||||
#[pest_ast(rule(Rule::circuit_member))]
|
#[pest_ast(rule(Rule::circuit_member))]
|
||||||
pub enum CircuitMember<'ast> {
|
pub enum CircuitMember<'ast> {
|
||||||
CircuitVariableDefinition(CircuitVariableDefinition<'ast>),
|
CircuitVariableDefinition(CircuitVariableDefinition<'ast>),
|
||||||
CircuitFunction(CircuitFunction<'ast>),
|
CircuitFunction(Function<'ast>),
|
||||||
}
|
}
|
||||||
|
@ -14,12 +14,7 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// 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/>.
|
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use crate::{
|
use crate::{ast::Rule, common::Identifier, types::Type, SpanDef};
|
||||||
ast::Rule,
|
|
||||||
common::{Identifier, Mutable},
|
|
||||||
types::Type,
|
|
||||||
SpanDef,
|
|
||||||
};
|
|
||||||
|
|
||||||
use pest::Span;
|
use pest::Span;
|
||||||
use pest_ast::FromPest;
|
use pest_ast::FromPest;
|
||||||
@ -28,7 +23,6 @@ use serde::Serialize;
|
|||||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
||||||
#[pest_ast(rule(Rule::circuit_variable_definition))]
|
#[pest_ast(rule(Rule::circuit_variable_definition))]
|
||||||
pub struct CircuitVariableDefinition<'ast> {
|
pub struct CircuitVariableDefinition<'ast> {
|
||||||
pub mutable: Option<Mutable>,
|
|
||||||
pub identifier: Identifier<'ast>,
|
pub identifier: Identifier<'ast>,
|
||||||
pub type_: Type<'ast>,
|
pub type_: Type<'ast>,
|
||||||
#[pest_ast(outer())]
|
#[pest_ast(outer())]
|
||||||
|
@ -23,8 +23,5 @@ pub use circuit_variable::*;
|
|||||||
pub mod circuit_variable_definition;
|
pub mod circuit_variable_definition;
|
||||||
pub use circuit_variable_definition::*;
|
pub use circuit_variable_definition::*;
|
||||||
|
|
||||||
pub mod circuit_function;
|
|
||||||
pub use circuit_function::*;
|
|
||||||
|
|
||||||
pub mod circuit_member;
|
pub mod circuit_member;
|
||||||
pub use circuit_member::*;
|
pub use circuit_member::*;
|
||||||
|
@ -35,6 +35,9 @@ pub use line_end::*;
|
|||||||
pub mod mutable;
|
pub mod mutable;
|
||||||
pub use mutable::*;
|
pub use mutable::*;
|
||||||
|
|
||||||
|
pub mod mut_self_keyword;
|
||||||
|
pub use mut_self_keyword::*;
|
||||||
|
|
||||||
pub mod range;
|
pub mod range;
|
||||||
pub use range::*;
|
pub use range::*;
|
||||||
|
|
||||||
|
@ -14,18 +14,29 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// 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/>.
|
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use crate::{ast::Rule, common::Static, functions::Function, SpanDef};
|
use crate::{
|
||||||
|
ast::Rule,
|
||||||
|
common::{Mutable, SelfKeyword},
|
||||||
|
SpanDef,
|
||||||
|
};
|
||||||
|
|
||||||
use pest::Span;
|
use pest::Span;
|
||||||
use pest_ast::FromPest;
|
use pest_ast::FromPest;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
||||||
#[pest_ast(rule(Rule::circuit_function))]
|
#[pest_ast(rule(Rule::mut_self_keyword))]
|
||||||
pub struct CircuitFunction<'ast> {
|
pub struct MutSelfKeyword<'ast> {
|
||||||
pub _static: Option<Static>,
|
pub mutable: Mutable,
|
||||||
pub function: Function<'ast>,
|
pub self_keyword: SelfKeyword<'ast>,
|
||||||
#[pest_ast(outer())]
|
#[pest_ast(outer())]
|
||||||
#[serde(with = "SpanDef")]
|
#[serde(with = "SpanDef")]
|
||||||
pub span: Span<'ast>,
|
pub span: Span<'ast>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'ast> fmt::Display for MutSelfKeyword<'ast> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "mut {}", self.self_keyword)
|
||||||
|
}
|
||||||
|
}
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::Rule,
|
ast::Rule,
|
||||||
|
common::{MutSelfKeyword, SelfKeyword},
|
||||||
functions::{FunctionInput, InputKeyword},
|
functions::{FunctionInput, InputKeyword},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -26,5 +27,7 @@ use serde::Serialize;
|
|||||||
#[pest_ast(rule(Rule::input))]
|
#[pest_ast(rule(Rule::input))]
|
||||||
pub enum Input<'ast> {
|
pub enum Input<'ast> {
|
||||||
InputKeyword(InputKeyword<'ast>),
|
InputKeyword(InputKeyword<'ast>),
|
||||||
|
SelfKeyword(SelfKeyword<'ast>),
|
||||||
|
MutSelfKeyword(MutSelfKeyword<'ast>),
|
||||||
FunctionInput(FunctionInput<'ast>),
|
FunctionInput(FunctionInput<'ast>),
|
||||||
}
|
}
|
||||||
|
@ -47,6 +47,9 @@ protected_name = {
|
|||||||
// Declared in common/self_keyword.rs
|
// Declared in common/self_keyword.rs
|
||||||
self_keyword = { "self" }
|
self_keyword = { "self" }
|
||||||
|
|
||||||
|
// Declared in common/mut_self_keyword.rs
|
||||||
|
mut_self_keyword = { mutable ~ self_keyword }
|
||||||
|
|
||||||
// Declared in common/self_keyword_or_identifier.rs
|
// Declared in common/self_keyword_or_identifier.rs
|
||||||
self_keyword_or_identifier = {
|
self_keyword_or_identifier = {
|
||||||
self_keyword
|
self_keyword
|
||||||
@ -319,13 +322,10 @@ circuit = { "circuit " ~ identifier ~ "{" ~ NEWLINE* ~ circuit_member* ~ NEWLINE
|
|||||||
circuit_variable = { identifier ~ ":" ~ expression }
|
circuit_variable = { identifier ~ ":" ~ expression }
|
||||||
|
|
||||||
// Declared in circuits/circuit_variable_definition.rs
|
// Declared in circuits/circuit_variable_definition.rs
|
||||||
circuit_variable_definition = { mutable? ~ identifier ~ ":" ~ type_ ~ ","?}
|
circuit_variable_definition = { identifier ~ ":" ~ type_ ~ ","?}
|
||||||
|
|
||||||
// Declared in circuits/circuit_function.rs
|
|
||||||
circuit_function = { static_? ~ function }
|
|
||||||
|
|
||||||
// Declared in circuits/circuit_member.rs
|
// Declared in circuits/circuit_member.rs
|
||||||
circuit_member = { circuit_function | circuit_variable_definition ~ NEWLINE*}
|
circuit_member = { function | circuit_variable_definition ~ NEWLINE*}
|
||||||
|
|
||||||
/// Conditionals
|
/// Conditionals
|
||||||
|
|
||||||
@ -429,6 +429,8 @@ input_keyword = { "input" }
|
|||||||
// Declared in functions/input/input.rs
|
// Declared in functions/input/input.rs
|
||||||
input = {
|
input = {
|
||||||
input_keyword
|
input_keyword
|
||||||
|
| self_keyword
|
||||||
|
| mut_self_keyword
|
||||||
| function_input
|
| function_input
|
||||||
}
|
}
|
||||||
input_tuple = _{ "(" ~ NEWLINE* ~ (input ~ ("," ~ NEWLINE* ~ input)* ~ ","?)? ~ NEWLINE* ~ ")"}
|
input_tuple = _{ "(" ~ NEWLINE* ~ (input ~ ("," ~ NEWLINE* ~ input)* ~ ","?)? ~ NEWLINE* ~ ")"}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "leo-imports"
|
name = "leo-imports"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
authors = [ "The Aleo Team <hello@aleo.org>" ]
|
authors = [ "The Aleo Team <hello@aleo.org>" ]
|
||||||
description = "Import parser for Leo program package dependencies"
|
description = "Import parser for Leo program package dependencies"
|
||||||
homepage = "https://aleo.org"
|
homepage = "https://aleo.org"
|
||||||
@ -19,11 +19,11 @@ edition = "2018"
|
|||||||
|
|
||||||
[dependencies.leo-ast]
|
[dependencies.leo-ast]
|
||||||
path = "../ast"
|
path = "../ast"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
|
|
||||||
[dependencies.leo-grammar]
|
[dependencies.leo-grammar]
|
||||||
path = "../grammar"
|
path = "../grammar"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
|
|
||||||
[dependencies.thiserror]
|
[dependencies.thiserror]
|
||||||
version = "1.0"
|
version = "1.0"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "leo-input"
|
name = "leo-input"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
authors = [ "The Aleo Team <hello@aleo.org>" ]
|
authors = [ "The Aleo Team <hello@aleo.org>" ]
|
||||||
description = "Input parser of the Leo programming language"
|
description = "Input parser of the Leo programming language"
|
||||||
homepage = "https://aleo.org"
|
homepage = "https://aleo.org"
|
||||||
|
@ -1 +1 @@
|
|||||||
v1.0.4
|
v1.0.6
|
@ -2,7 +2,7 @@ dependencies = { }
|
|||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "leo-linter"
|
name = "leo-linter"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
authors = [ "The Aleo Team <hello@aleo.org>" ]
|
authors = [ "The Aleo Team <hello@aleo.org>" ]
|
||||||
description = "Linter of the Leo programming language"
|
description = "Linter of the Leo programming language"
|
||||||
homepage = "https://aleo.org"
|
homepage = "https://aleo.org"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "leo-package"
|
name = "leo-package"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
authors = [ "The Aleo Team <hello@aleo.org>" ]
|
authors = [ "The Aleo Team <hello@aleo.org>" ]
|
||||||
description = "Package parser of the Leo programming language"
|
description = "Package parser of the Leo programming language"
|
||||||
homepage = "https://aleo.org"
|
homepage = "https://aleo.org"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "leo-state"
|
name = "leo-state"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
authors = [ "The Aleo Team <hello@aleo.org>" ]
|
authors = [ "The Aleo Team <hello@aleo.org>" ]
|
||||||
description = "State parser of the Leo programming language"
|
description = "State parser of the Leo programming language"
|
||||||
homepage = "https://aleo.org"
|
homepage = "https://aleo.org"
|
||||||
@ -19,11 +19,11 @@ edition = "2018"
|
|||||||
|
|
||||||
[dependencies.leo-input]
|
[dependencies.leo-input]
|
||||||
path = "../input"
|
path = "../input"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
|
|
||||||
[dependencies.leo-ast]
|
[dependencies.leo-ast]
|
||||||
path = "../ast"
|
path = "../ast"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
|
|
||||||
[dependencies.snarkos-algorithms]
|
[dependencies.snarkos-algorithms]
|
||||||
version = "1.1.3"
|
version = "1.1.3"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "leo-symbol-table"
|
name = "leo-symbol-table"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
authors = [ "The Aleo Team <hello@aleo.org>" ]
|
authors = [ "The Aleo Team <hello@aleo.org>" ]
|
||||||
description = "Stores user-defined variables during type resolution"
|
description = "Stores user-defined variables during type resolution"
|
||||||
homepage = "https://aleo.org"
|
homepage = "https://aleo.org"
|
||||||
@ -19,19 +19,19 @@ edition = "2018"
|
|||||||
|
|
||||||
[dependencies.leo-ast]
|
[dependencies.leo-ast]
|
||||||
path = "../ast"
|
path = "../ast"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
|
|
||||||
[dependencies.leo-core]
|
[dependencies.leo-core]
|
||||||
path = "../core"
|
path = "../core"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
|
|
||||||
[dependencies.leo-grammar]
|
[dependencies.leo-grammar]
|
||||||
path = "../grammar"
|
path = "../grammar"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
|
|
||||||
[dependencies.leo-imports]
|
[dependencies.leo-imports]
|
||||||
path = "../imports"
|
path = "../imports"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
|
|
||||||
[dependencies.serde]
|
[dependencies.serde]
|
||||||
version = "1.0"
|
version = "1.0"
|
||||||
|
@ -14,14 +14,7 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// 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/>.
|
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use crate::{
|
use crate::{types::circuits::CircuitVariableType, FunctionType, SymbolTable, Type, TypeError};
|
||||||
types::circuits::{CircuitFunctionType, CircuitVariableType},
|
|
||||||
Attribute,
|
|
||||||
FunctionType,
|
|
||||||
SymbolTable,
|
|
||||||
Type,
|
|
||||||
TypeError,
|
|
||||||
};
|
|
||||||
use leo_ast::{Circuit, CircuitMember, Identifier, InputValue, Parameter, Span};
|
use leo_ast::{Circuit, CircuitMember, Identifier, InputValue, Parameter, Span};
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@ -43,7 +36,7 @@ pub struct CircuitType {
|
|||||||
pub variables: Vec<CircuitVariableType>,
|
pub variables: Vec<CircuitVariableType>,
|
||||||
|
|
||||||
/// The circuit functions.
|
/// The circuit functions.
|
||||||
pub functions: Vec<CircuitFunctionType>,
|
pub functions: Vec<FunctionType>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CircuitType {
|
impl CircuitType {
|
||||||
@ -61,7 +54,7 @@ impl CircuitType {
|
|||||||
// Resolve the type of every circuit member.
|
// Resolve the type of every circuit member.
|
||||||
for member in unresolved.members {
|
for member in unresolved.members {
|
||||||
match member {
|
match member {
|
||||||
CircuitMember::CircuitVariable(is_mutable, variable_identifier, type_) => {
|
CircuitMember::CircuitVariable(variable_identifier, type_) => {
|
||||||
// Resolve the type of the circuit member variable.
|
// Resolve the type of the circuit member variable.
|
||||||
let type_ = Type::new_from_circuit(
|
let type_ = Type::new_from_circuit(
|
||||||
table,
|
table,
|
||||||
@ -70,34 +63,22 @@ impl CircuitType {
|
|||||||
circuit_identifier.span.clone(),
|
circuit_identifier.span.clone(),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// Check if the circuit member variable is mutable.
|
|
||||||
let attribute = if is_mutable { Some(Attribute::Mutable) } else { None };
|
|
||||||
|
|
||||||
// Create a new circuit variable type.
|
// Create a new circuit variable type.
|
||||||
let variable = CircuitVariableType {
|
let variable = CircuitVariableType {
|
||||||
identifier: variable_identifier,
|
identifier: variable_identifier,
|
||||||
type_,
|
type_,
|
||||||
attribute,
|
attribute: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Store the circuit variable type.
|
// Store the circuit variable type.
|
||||||
variables.push(variable);
|
variables.push(variable);
|
||||||
}
|
}
|
||||||
CircuitMember::CircuitFunction(is_static, function) => {
|
CircuitMember::CircuitFunction(function) => {
|
||||||
// Resolve the type of the circuit member function.
|
// Resolve the type of the circuit member function.
|
||||||
let function_type = FunctionType::from_circuit(table, circuit_identifier.clone(), function)?;
|
let function_type = FunctionType::from_circuit(table, circuit_identifier.clone(), function)?;
|
||||||
|
|
||||||
// Check if the circuit member function is static.
|
|
||||||
let attribute = if is_static { Some(Attribute::Static) } else { None };
|
|
||||||
|
|
||||||
// Create a new circuit function type.
|
|
||||||
let function = CircuitFunctionType {
|
|
||||||
function: function_type,
|
|
||||||
attribute,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Store the circuit function type.
|
// Store the circuit function type.
|
||||||
functions.push(function);
|
functions.push(function_type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -113,10 +94,10 @@ impl CircuitType {
|
|||||||
///
|
///
|
||||||
/// Returns the function type of a circuit member given an identifier.
|
/// Returns the function type of a circuit member given an identifier.
|
||||||
///
|
///
|
||||||
pub fn member_function_type(&self, identifier: &Identifier) -> Option<&CircuitFunctionType> {
|
pub fn member_function_type(&self, identifier: &Identifier) -> Option<&FunctionType> {
|
||||||
self.functions
|
self.functions
|
||||||
.iter()
|
.iter()
|
||||||
.find(|function| function.function.identifier.eq(identifier))
|
.find(|function| function.identifier.eq(identifier))
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@ -139,7 +120,7 @@ impl CircuitType {
|
|||||||
let matched_function = self.member_function_type(identifier);
|
let matched_function = self.member_function_type(identifier);
|
||||||
|
|
||||||
match matched_function {
|
match matched_function {
|
||||||
Some(function) => Ok(Type::Function(function.function.identifier.to_owned())),
|
Some(function) => Ok(Type::Function(function.identifier.to_owned())),
|
||||||
None => Err(TypeError::undefined_circuit_member(identifier.clone())),
|
None => Err(TypeError::undefined_circuit_member(identifier.clone())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,8 +17,5 @@
|
|||||||
pub mod circuit;
|
pub mod circuit;
|
||||||
pub use self::circuit::*;
|
pub use self::circuit::*;
|
||||||
|
|
||||||
pub mod circuit_function;
|
|
||||||
pub use self::circuit_function::*;
|
|
||||||
|
|
||||||
pub mod circuit_variable;
|
pub mod circuit_variable;
|
||||||
pub use self::circuit_variable::*;
|
pub use self::circuit_variable::*;
|
||||||
|
@ -119,6 +119,34 @@ impl FunctionType {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Returns the number of input variables to the function.
|
||||||
|
/// The `self` and `mut self` keywords are not counted as input variables.
|
||||||
|
///
|
||||||
|
pub fn num_inputs(&self) -> usize {
|
||||||
|
self.inputs
|
||||||
|
.iter()
|
||||||
|
.fold(0, |acc, function_input| acc + function_input.count())
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Returns `true` if the input `self` or `mut self` is present.
|
||||||
|
/// Returns `false` otherwise.
|
||||||
|
///
|
||||||
|
pub fn contains_self(&self) -> bool {
|
||||||
|
self.inputs.iter().any(|param| param.is_self())
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Returns a vector of [&FunctionInputType] removing `self` and `mut self` inputs.
|
||||||
|
///
|
||||||
|
pub fn filter_self_inputs(&self) -> Vec<&FunctionInputType> {
|
||||||
|
self.inputs
|
||||||
|
.iter()
|
||||||
|
.filter(|input| !input.is_self())
|
||||||
|
.collect::<Vec<&FunctionInputType>>()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for FunctionType {
|
impl PartialEq for FunctionType {
|
||||||
|
@ -22,6 +22,8 @@ use serde::{Deserialize, Serialize};
|
|||||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub enum FunctionInputType {
|
pub enum FunctionInputType {
|
||||||
InputKeyword(Identifier),
|
InputKeyword(Identifier),
|
||||||
|
SelfKeyword(Identifier),
|
||||||
|
MutSelfKeyword(Identifier),
|
||||||
Variable(FunctionInputVariableType),
|
Variable(FunctionInputVariableType),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,6 +34,8 @@ impl FunctionInputType {
|
|||||||
pub fn identifier(&self) -> &Identifier {
|
pub fn identifier(&self) -> &Identifier {
|
||||||
match self {
|
match self {
|
||||||
FunctionInputType::InputKeyword(identifier) => identifier,
|
FunctionInputType::InputKeyword(identifier) => identifier,
|
||||||
|
FunctionInputType::SelfKeyword(identifier) => identifier,
|
||||||
|
FunctionInputType::MutSelfKeyword(identifier) => identifier,
|
||||||
FunctionInputType::Variable(variable) => &variable.identifier,
|
FunctionInputType::Variable(variable) => &variable.identifier,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -42,6 +46,8 @@ impl FunctionInputType {
|
|||||||
pub fn type_(&self) -> Type {
|
pub fn type_(&self) -> Type {
|
||||||
match self {
|
match self {
|
||||||
FunctionInputType::InputKeyword(identifier) => Type::Circuit(identifier.to_owned()),
|
FunctionInputType::InputKeyword(identifier) => Type::Circuit(identifier.to_owned()),
|
||||||
|
FunctionInputType::SelfKeyword(identifier) => Type::Circuit(identifier.to_owned()),
|
||||||
|
FunctionInputType::MutSelfKeyword(identifier) => Type::Circuit(identifier.to_owned()),
|
||||||
FunctionInputType::Variable(variable) => variable.type_.to_owned(),
|
FunctionInputType::Variable(variable) => variable.type_.to_owned(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -52,10 +58,34 @@ impl FunctionInputType {
|
|||||||
pub fn span(&self) -> &Span {
|
pub fn span(&self) -> &Span {
|
||||||
match self {
|
match self {
|
||||||
FunctionInputType::InputKeyword(identifier) => &identifier.span,
|
FunctionInputType::InputKeyword(identifier) => &identifier.span,
|
||||||
|
FunctionInputType::SelfKeyword(identifier) => &identifier.span,
|
||||||
|
FunctionInputType::MutSelfKeyword(identifier) => &identifier.span,
|
||||||
FunctionInputType::Variable(variable) => &variable.span,
|
FunctionInputType::Variable(variable) => &variable.span,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Returns `true` if input `self` or `mut self` is present.
|
||||||
|
/// Returns `false` otherwise.
|
||||||
|
///
|
||||||
|
pub fn is_self(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
FunctionInputType::InputKeyword(_) => false,
|
||||||
|
FunctionInputType::SelfKeyword(_) => true,
|
||||||
|
FunctionInputType::MutSelfKeyword(_) => true,
|
||||||
|
FunctionInputType::Variable(_) => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Returns `0` if the function input is a `self` or `mut self` keyword which does not have to
|
||||||
|
/// provided in a call to the function.
|
||||||
|
/// Returns `1` if a variable must be provided in a call to the function.
|
||||||
|
///
|
||||||
|
pub fn count(&self) -> usize {
|
||||||
|
if self.is_self() { 0 } else { 1 }
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Return a new `FunctionInputType` from a given `FunctionInput`.
|
/// Return a new `FunctionInputType` from a given `FunctionInput`.
|
||||||
///
|
///
|
||||||
@ -64,7 +94,9 @@ impl FunctionInputType {
|
|||||||
///
|
///
|
||||||
pub fn new(table: &SymbolTable, unresolved: FunctionInput) -> Result<Self, TypeError> {
|
pub fn new(table: &SymbolTable, unresolved: FunctionInput) -> Result<Self, TypeError> {
|
||||||
Ok(match unresolved {
|
Ok(match unresolved {
|
||||||
FunctionInput::InputKeyword(identifier) => FunctionInputType::InputKeyword(identifier),
|
FunctionInput::InputKeyword(keyword) => FunctionInputType::InputKeyword(Identifier::from(keyword)),
|
||||||
|
FunctionInput::SelfKeyword(_) => unimplemented!("cannot call self keyword from non-circuit context"),
|
||||||
|
FunctionInput::MutSelfKeyword(_) => unimplemented!("cannot call mut self keyword from non-circuit context"),
|
||||||
FunctionInput::Variable(variable) => {
|
FunctionInput::Variable(variable) => {
|
||||||
let variable_resolved = FunctionInputVariableType::new(table, variable)?;
|
let variable_resolved = FunctionInputVariableType::new(table, variable)?;
|
||||||
|
|
||||||
@ -88,7 +120,13 @@ impl FunctionInputType {
|
|||||||
circuit_name: Identifier,
|
circuit_name: Identifier,
|
||||||
) -> Result<Self, TypeError> {
|
) -> Result<Self, TypeError> {
|
||||||
Ok(match unresolved {
|
Ok(match unresolved {
|
||||||
FunctionInput::InputKeyword(identifier) => FunctionInputType::InputKeyword(identifier),
|
FunctionInput::InputKeyword(keyword) => FunctionInputType::InputKeyword(Identifier::from(keyword)),
|
||||||
|
FunctionInput::SelfKeyword(keyword) => {
|
||||||
|
FunctionInputType::SelfKeyword(Identifier::new_with_span(&circuit_name.name, &keyword.span))
|
||||||
|
}
|
||||||
|
FunctionInput::MutSelfKeyword(keyword) => {
|
||||||
|
FunctionInputType::MutSelfKeyword(Identifier::new_with_span(&circuit_name.name, &keyword.span))
|
||||||
|
}
|
||||||
FunctionInput::Variable(unresolved_function_input) => {
|
FunctionInput::Variable(unresolved_function_input) => {
|
||||||
let function_input =
|
let function_input =
|
||||||
FunctionInputVariableType::new_from_circuit(table, unresolved_function_input, circuit_name)?;
|
FunctionInputVariableType::new_from_circuit(table, unresolved_function_input, circuit_name)?;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "leo-type-inference"
|
name = "leo-type-inference"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
authors = [ "The Aleo Team <hello@aleo.org>" ]
|
authors = [ "The Aleo Team <hello@aleo.org>" ]
|
||||||
description = "Checks that a program is correct using type inference"
|
description = "Checks that a program is correct using type inference"
|
||||||
homepage = "https://aleo.org"
|
homepage = "https://aleo.org"
|
||||||
@ -19,19 +19,19 @@ edition = "2018"
|
|||||||
|
|
||||||
[dependencies.leo-ast]
|
[dependencies.leo-ast]
|
||||||
path = "../ast"
|
path = "../ast"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
|
|
||||||
[dependencies.leo-imports]
|
[dependencies.leo-imports]
|
||||||
path = "../imports"
|
path = "../imports"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
|
|
||||||
[dependencies.leo-grammar]
|
[dependencies.leo-grammar]
|
||||||
path = "../grammar"
|
path = "../grammar"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
|
|
||||||
[dependencies.leo-symbol-table]
|
[dependencies.leo-symbol-table]
|
||||||
path = "../symbol-table"
|
path = "../symbol-table"
|
||||||
version = "1.0.4"
|
version = "1.0.6"
|
||||||
|
|
||||||
[dependencies.serde_json]
|
[dependencies.serde_json]
|
||||||
version = "1.0"
|
version = "1.0"
|
||||||
|
@ -172,6 +172,27 @@ impl FrameError {
|
|||||||
Self::new_from_span(message, span)
|
Self::new_from_span(message, span)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// The `self` keyword was used in a static circuit function signature.
|
||||||
|
///
|
||||||
|
pub fn self_not_available(span: &Span) -> Self {
|
||||||
|
let message = "keyword `self` is only available in static circuit functions.".to_string();
|
||||||
|
|
||||||
|
Self::new_from_span(message, span)
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// A static function was accessed using dot `.` syntax instead of double colon `::` syntax.
|
||||||
|
///
|
||||||
|
pub fn static_call_invalid(identifier: &Identifier) -> Self {
|
||||||
|
let message = format!(
|
||||||
|
"Static function `{}` must be called using double colon `::` syntax.",
|
||||||
|
identifier.name
|
||||||
|
);
|
||||||
|
|
||||||
|
Self::new_from_span(message, &identifier.span)
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Attempted to access the index of a non-tuple type.
|
/// Attempted to access the index of a non-tuple type.
|
||||||
///
|
///
|
||||||
|
@ -34,7 +34,7 @@ use leo_ast::{
|
|||||||
Statement,
|
Statement,
|
||||||
Variables,
|
Variables,
|
||||||
};
|
};
|
||||||
use leo_symbol_table::{Attribute, CircuitFunctionType, CircuitType, FunctionType, SymbolTable, Type, TypeVariable};
|
use leo_symbol_table::{CircuitType, FunctionType, SymbolTable, Type, TypeVariable};
|
||||||
|
|
||||||
/// A vector of `TypeAssertion` predicates created from a function body.
|
/// A vector of `TypeAssertion` predicates created from a function body.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -100,13 +100,13 @@ impl Frame {
|
|||||||
let identifier = &function.identifier;
|
let identifier = &function.identifier;
|
||||||
|
|
||||||
// Find function name in circuit members.
|
// Find function name in circuit members.
|
||||||
let circuit_function_type = self_type.member_function_type(identifier).unwrap().to_owned();
|
let function_type = self_type.member_function_type(identifier).unwrap().to_owned();
|
||||||
|
|
||||||
// Create a new scope for the function variables.
|
// Create a new scope for the function variables.
|
||||||
let mut scope = Scope::new(Some(parent_scope));
|
let mut scope = Scope::new(Some(parent_scope));
|
||||||
|
|
||||||
// Initialize function inputs as variables.
|
// Initialize function inputs as variables.
|
||||||
scope.insert_function_inputs(&circuit_function_type.function.inputs)?;
|
scope.insert_function_inputs(&function_type.inputs)?;
|
||||||
|
|
||||||
// Create new list of scopes for frame.
|
// Create new list of scopes for frame.
|
||||||
let scopes = vec![scope];
|
let scopes = vec![scope];
|
||||||
@ -114,7 +114,7 @@ impl Frame {
|
|||||||
// Create new frame struct.
|
// Create new frame struct.
|
||||||
// Update variables when encountering let/const variable definitions.
|
// Update variables when encountering let/const variable definitions.
|
||||||
let mut frame = Self {
|
let mut frame = Self {
|
||||||
function_type: circuit_function_type.function,
|
function_type,
|
||||||
self_type: Some(self_type),
|
self_type: Some(self_type),
|
||||||
scopes,
|
scopes,
|
||||||
statements: function.statements,
|
statements: function.statements,
|
||||||
@ -955,22 +955,6 @@ impl Frame {
|
|||||||
Ok(Type::Circuit(circuit_type.identifier))
|
Ok(Type::Circuit(circuit_type.identifier))
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
|
||||||
/// Returns the type of the accessed circuit member when called as an expression.
|
|
||||||
///
|
|
||||||
fn parse_expression_circuit_member_access(
|
|
||||||
&mut self,
|
|
||||||
expression: &Expression,
|
|
||||||
identifier: &Identifier,
|
|
||||||
span: &Span,
|
|
||||||
) -> Result<Type, FrameError> {
|
|
||||||
// Parse circuit name.
|
|
||||||
let type_ = self.parse_expression(expression)?;
|
|
||||||
|
|
||||||
// Parse the circuit member access.
|
|
||||||
self.parse_circuit_member_access(type_, identifier, span)
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Returns the type of the accessed circuit member.
|
/// Returns the type of the accessed circuit member.
|
||||||
///
|
///
|
||||||
@ -987,6 +971,22 @@ impl Frame {
|
|||||||
Ok(circuit_type.member_type(&identifier)?)
|
Ok(circuit_type.member_type(&identifier)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Returns the type of the accessed circuit member when called as an expression.
|
||||||
|
///
|
||||||
|
fn parse_expression_circuit_member_access(
|
||||||
|
&mut self,
|
||||||
|
expression: &Expression,
|
||||||
|
identifier: &Identifier,
|
||||||
|
span: &Span,
|
||||||
|
) -> Result<Type, FrameError> {
|
||||||
|
// Parse circuit name.
|
||||||
|
let type_ = self.parse_expression(expression)?;
|
||||||
|
|
||||||
|
// Parse the circuit member access.
|
||||||
|
self.parse_circuit_member_access(type_, identifier, span)
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Returns the type returned by calling the static circuit function.
|
/// Returns the type returned by calling the static circuit function.
|
||||||
///
|
///
|
||||||
@ -1029,10 +1029,10 @@ impl Frame {
|
|||||||
match expression {
|
match expression {
|
||||||
Expression::Identifier(identifier) => self.parse_program_function(identifier, span),
|
Expression::Identifier(identifier) => self.parse_program_function(identifier, span),
|
||||||
Expression::CircuitMemberAccess(expression, identifier, span) => {
|
Expression::CircuitMemberAccess(expression, identifier, span) => {
|
||||||
self.parse_circuit_function(expression, identifier, span)
|
self.parse_circuit_function(expression, identifier, span, false)
|
||||||
}
|
}
|
||||||
Expression::CircuitStaticFunctionAccess(expression, identifier, span) => {
|
Expression::CircuitStaticFunctionAccess(expression, identifier, span) => {
|
||||||
self.parse_static_circuit_function(expression, identifier, span)
|
self.parse_circuit_function(expression, identifier, span, true)
|
||||||
}
|
}
|
||||||
expression => Err(FrameError::invalid_function(expression, span)),
|
expression => Err(FrameError::invalid_function(expression, span)),
|
||||||
}
|
}
|
||||||
@ -1056,7 +1056,7 @@ impl Frame {
|
|||||||
expression: &Expression,
|
expression: &Expression,
|
||||||
identifier: &Identifier,
|
identifier: &Identifier,
|
||||||
span: &Span,
|
span: &Span,
|
||||||
) -> Result<&CircuitFunctionType, FrameError> {
|
) -> Result<&FunctionType, FrameError> {
|
||||||
// Parse circuit name.
|
// Parse circuit name.
|
||||||
let type_ = self.parse_expression(expression)?;
|
let type_ = self.parse_expression(expression)?;
|
||||||
|
|
||||||
@ -1077,37 +1077,25 @@ impl Frame {
|
|||||||
expression: &Expression,
|
expression: &Expression,
|
||||||
identifier: &Identifier,
|
identifier: &Identifier,
|
||||||
span: &Span,
|
span: &Span,
|
||||||
|
is_static: bool,
|
||||||
) -> Result<FunctionType, FrameError> {
|
) -> Result<FunctionType, FrameError> {
|
||||||
// Find circuit function type.
|
// Find circuit function type.
|
||||||
let circuit_function_type = self.parse_circuit_function_type(expression, identifier, span)?;
|
let function_type = self.parse_circuit_function_type(expression, identifier, span)?;
|
||||||
|
|
||||||
// Check that the function is non-static.
|
// Case 1: static call + self keyword => Error
|
||||||
if let Some(Attribute::Static) = circuit_function_type.attribute {
|
// Case 2: no static call + no self keywords => Error
|
||||||
return Err(FrameError::invalid_static_access(identifier));
|
// Case 3: static call + no self keywords => Ok
|
||||||
|
// Case 4: no static call + self keyword => Ok
|
||||||
|
if is_static && function_type.contains_self() {
|
||||||
|
return Err(FrameError::self_not_available(&identifier.span));
|
||||||
|
} else if !is_static && !function_type.contains_self() {
|
||||||
|
return Err(FrameError::static_call_invalid(&identifier));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if is_static && function_type.contains_self() {}
|
||||||
|
|
||||||
// Return the function type.
|
// Return the function type.
|
||||||
Ok(circuit_function_type.function.to_owned())
|
Ok(function_type.to_owned())
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
/// Returns a `FunctionType` given a circuit expression and static function identifier.
|
|
||||||
///
|
|
||||||
fn parse_static_circuit_function(
|
|
||||||
&mut self,
|
|
||||||
expression: &Expression,
|
|
||||||
identifier: &Identifier,
|
|
||||||
span: &Span,
|
|
||||||
) -> Result<FunctionType, FrameError> {
|
|
||||||
// Find circuit function type.
|
|
||||||
let circuit_function_type = self.parse_circuit_function_type(expression, identifier, span)?;
|
|
||||||
|
|
||||||
// Check that the function is static.
|
|
||||||
if let Some(Attribute::Static) = circuit_function_type.attribute {
|
|
||||||
Ok(circuit_function_type.function.to_owned())
|
|
||||||
} else {
|
|
||||||
Err(FrameError::invalid_member_access(identifier))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@ -1125,12 +1113,17 @@ impl Frame {
|
|||||||
let function_type = self.parse_function_name(expression, span)?;
|
let function_type = self.parse_function_name(expression, span)?;
|
||||||
|
|
||||||
// Check the length of arguments
|
// Check the length of arguments
|
||||||
if function_type.inputs.len() != inputs.len() {
|
let num_inputs = function_type.num_inputs();
|
||||||
return Err(FrameError::num_inputs(function_type.inputs.len(), inputs.len(), span));
|
|
||||||
|
if num_inputs != inputs.len() {
|
||||||
|
return Err(FrameError::num_inputs(num_inputs, inputs.len(), span));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Filter out `self` and `mut self` keywords.
|
||||||
|
let expected_inputs = function_type.filter_self_inputs();
|
||||||
|
|
||||||
// Assert function inputs are correct types.
|
// Assert function inputs are correct types.
|
||||||
for (expected_input, actual_input) in function_type.inputs.iter().zip(inputs) {
|
for (expected_input, actual_input) in expected_inputs.iter().zip(inputs) {
|
||||||
// Parse expected input type.
|
// Parse expected input type.
|
||||||
let expected_type = expected_input.type_();
|
let expected_type = expected_input.type_();
|
||||||
|
|
||||||
|
@ -82,7 +82,7 @@ impl TypeInference {
|
|||||||
// Create a new function for each circuit member function.
|
// Create a new function for each circuit member function.
|
||||||
for circuit_member in &circuit.members {
|
for circuit_member in &circuit.members {
|
||||||
// ignore circuit member variables
|
// ignore circuit member variables
|
||||||
if let CircuitMember::CircuitFunction(_, function) = circuit_member {
|
if let CircuitMember::CircuitFunction(function) = circuit_member {
|
||||||
// Collect `TypeAssertion` predicates from the function.
|
// Collect `TypeAssertion` predicates from the function.
|
||||||
// Pass down circuit self type and circuit variable types to each function.
|
// Pass down circuit self type and circuit variable types to each function.
|
||||||
let frame = Frame::new_circuit_function(
|
let frame = Frame::new_circuit_function(
|
||||||
|
Loading…
Reference in New Issue
Block a user