diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8afe275808..ab07ada1dc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -43,7 +43,7 @@ jobs: matrix: rust: - stable - - nightly +# - nightly steps: - name: Checkout @@ -70,12 +70,12 @@ jobs: 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' +# - name: Check benchmarks on nightly +# uses: actions-rs/cargo@v1 +# with: +# command: clippy +# args: --all-features --examples --all --benches +# if: matrix.rust == 'nightly' test: name: Test diff --git a/.rustfmt.toml b/.rustfmt.toml index e86fa4f991..39028b1340 100644 --- a/.rustfmt.toml +++ b/.rustfmt.toml @@ -10,7 +10,7 @@ use_try_shorthand = true # Nightly configurations imports_layout = "HorizontalVertical" license_template_path = ".resources/license_header" -merge_imports = true +imports_granularity = "Crate" overflow_delimited_expr = true reorder_impl_items = true version = "Two" diff --git a/Cargo.lock b/Cargo.lock index 412c5102fe..279f4eaae0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -917,6 +917,17 @@ dependencies = [ "wasi 0.9.0+wasi-snapshot-preview1", ] +[[package]] +name = "getrandom" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "wasi 0.10.0+wasi-snapshot-preview1", +] + [[package]] name = "gimli" version = "0.23.0" @@ -1219,6 +1230,21 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" +[[package]] +name = "leo-asg" +version = "1.0.8" +dependencies = [ + "criterion", + "indexmap", + "leo-ast", + "leo-grammar", + "num-bigint", + "serde", + "serde_json", + "thiserror", + "uuid", +] + [[package]] name = "leo-ast" version = "1.0.8" @@ -2070,7 +2096,7 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" dependencies = [ - "getrandom", + "getrandom 0.1.15", "libc", "rand_chacha", "rand_core 0.5.1", @@ -2093,7 +2119,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" dependencies = [ - "getrandom", + "getrandom 0.1.15", ] [[package]] @@ -2157,7 +2183,7 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de0737333e7a9502c789a36d7c7fa6092a49895d4faa31ca5df163857ded2e9d" dependencies = [ - "getrandom", + "getrandom 0.1.15", "redox_syscall", "rust-argon2", ] @@ -3106,6 +3132,16 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "uuid" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" +dependencies = [ + "getrandom 0.2.2", + "serde", +] + [[package]] name = "vcpkg" version = "0.2.11" diff --git a/Cargo.toml b/Cargo.toml index 41b49d25d6..129dbe8739 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,6 +36,7 @@ members = [ "linter", "package", "state", + "asg", "symbol-table", "type-inference" ] diff --git a/asg/Cargo.toml b/asg/Cargo.toml new file mode 100644 index 0000000000..de3fa8f179 --- /dev/null +++ b/asg/Cargo.toml @@ -0,0 +1,48 @@ +[package] +name = "leo-asg" +version = "1.0.8" +authors = [ "The Aleo Team " ] +description = "ASG of the Leo programming language" +homepage = "https://aleo.org" +repository = "https://github.com/AleoHQ/leo" +keywords = [ + "aleo", + "cryptography", + "leo", + "programming-language", + "zero-knowledge" +] +categories = [ "cryptography::cryptocurrencies", "web-programming" ] +include = [ "Cargo.toml", "src", "README.md", "LICENSE.md" ] +license = "GPL-3.0" +edition = "2018" + +[dependencies.serde] +version = "1.0" + +[dependencies.serde_json] +version = "1.0" + +[dev-dependencies.criterion] +version = "0.3" + +[dependencies.indexmap] +version = "1.6" + +[dependencies.thiserror] +version = "1.0" + +[dependencies.leo-ast] +version = "1.0" +path = "../ast" + +[dependencies.leo-grammar] +version = "1.0" +path = "../grammar" + +[dependencies.uuid] +version = "0.8" +features = ["v4", "serde"] + +[dependencies.num-bigint] +version = "0.3" \ No newline at end of file diff --git a/asg/src/checks/mod.rs b/asg/src/checks/mod.rs new file mode 100644 index 0000000000..d143db3fa2 --- /dev/null +++ b/asg/src/checks/mod.rs @@ -0,0 +1,20 @@ +// 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 . + +//! Helper methods to determine the correct return value path in an asg. + +mod return_path; +pub use return_path::*; diff --git a/asg/src/checks/return_path.rs b/asg/src/checks/return_path.rs new file mode 100644 index 0000000000..1880b12593 --- /dev/null +++ b/asg/src/checks/return_path.rs @@ -0,0 +1,127 @@ +// 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 . + +use crate::{ + statement::*, + BoolAnd, + Expression, + Monoid, + MonoidalReducerExpression, + MonoidalReducerStatement, + Node, + Span, +}; + +use std::sync::Arc; + +pub struct ReturnPathReducer { + pub errors: Vec<(Span, String)>, +} + +impl ReturnPathReducer { + fn record_error(&mut self, span: Option<&Span>, error: String) { + self.errors.push((span.cloned().unwrap_or_default(), error)); + } + + pub fn new() -> ReturnPathReducer { + ReturnPathReducer { errors: vec![] } + } +} + +impl Default for ReturnPathReducer { + fn default() -> Self { + Self::new() + } +} + +#[allow(unused_variables)] +impl MonoidalReducerExpression for ReturnPathReducer { + fn reduce_expression(&mut self, input: &Arc, value: BoolAnd) -> BoolAnd { + BoolAnd(false) + } +} + +#[allow(unused_variables)] +impl MonoidalReducerStatement for ReturnPathReducer { + fn reduce_assign_access(&mut self, input: &AssignAccess, left: Option, right: Option) -> BoolAnd { + BoolAnd(false) + } + + fn reduce_assign(&mut self, input: &AssignStatement, accesses: Vec, value: BoolAnd) -> BoolAnd { + BoolAnd(false) + } + + fn reduce_block(&mut self, input: &BlockStatement, statements: Vec) -> BoolAnd { + if statements.is_empty() { + BoolAnd(false) + } else if let Some(index) = statements[..statements.len() - 1].iter().map(|x| x.0).position(|x| x) { + self.record_error( + input.statements[index].span(), + "dead code due to unconditional early return".to_string(), + ); + BoolAnd(true) + } else { + BoolAnd(statements[statements.len() - 1].0) + } + } + + fn reduce_conditional_statement( + &mut self, + input: &ConditionalStatement, + condition: BoolAnd, + if_true: BoolAnd, + if_false: Option, + ) -> BoolAnd { + if if_false.as_ref().map(|x| x.0).unwrap_or(false) != if_true.0 { + self.record_error( + input.span(), + "cannot have asymmetrical return in if statement".to_string(), + ); + } + if_true.append(if_false.unwrap_or(BoolAnd(false))) + } + + fn reduce_formatted_string(&mut self, input: &FormattedString, parameters: Vec) -> BoolAnd { + BoolAnd(false) + } + + fn reduce_console(&mut self, input: &ConsoleStatement, argument: BoolAnd) -> BoolAnd { + BoolAnd(false) + } + + fn reduce_definition(&mut self, input: &DefinitionStatement, value: BoolAnd) -> BoolAnd { + BoolAnd(false) + } + + fn reduce_expression_statement(&mut self, input: &ExpressionStatement, expression: BoolAnd) -> BoolAnd { + BoolAnd(false) + } + + fn reduce_iteration( + &mut self, + input: &IterationStatement, + start: BoolAnd, + stop: BoolAnd, + body: BoolAnd, + ) -> BoolAnd { + // loops are const defined ranges, so we could probably check if they run one and emit here + BoolAnd(false) + } + + fn reduce_return(&mut self, input: &ReturnStatement, value: BoolAnd) -> BoolAnd { + BoolAnd(true) + } +} diff --git a/asg/src/const_value.rs b/asg/src/const_value.rs new file mode 100644 index 0000000000..b3c9819446 --- /dev/null +++ b/asg/src/const_value.rs @@ -0,0 +1,277 @@ +// 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 . + +use crate::{AsgConvertError, IntegerType, Span, Type}; + +use num_bigint::BigInt; +use std::{convert::TryInto, fmt}; + +/// Constant integer values in a program. +#[derive(Clone, Debug, PartialEq)] +pub enum ConstInt { + I8(i8), + I16(i16), + I32(i32), + I64(i64), + I128(i128), + U8(u8), + U16(u16), + U32(u32), + U64(u64), + U128(u128), +} + +/// Specifies how to calculate a group coordinate in a program. +#[derive(Clone, Debug, PartialEq)] +pub enum GroupCoordinate { + /// Explicit field element number string. + Number(String), + + /// Attempt to recover with a sign high bit. + SignHigh, + + /// Attempt to recover with a sign low bit. + SignLow, + + /// Try recovering with a sign low - upon failure try sign high. + Inferred, +} + +impl fmt::Display for GroupCoordinate { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + GroupCoordinate::Number(number) => write!(f, "{}", number), + GroupCoordinate::SignHigh => write!(f, "+"), + GroupCoordinate::SignLow => write!(f, "-"), + GroupCoordinate::Inferred => write!(f, "_"), + } + } +} + +impl From<&leo_ast::GroupCoordinate> for GroupCoordinate { + fn from(other: &leo_ast::GroupCoordinate) -> GroupCoordinate { + use leo_ast::GroupCoordinate::*; + match other { + Number(value, _) => GroupCoordinate::Number(value.clone()), + SignHigh => GroupCoordinate::SignHigh, + SignLow => GroupCoordinate::SignLow, + Inferred => GroupCoordinate::Inferred, + } + } +} + +impl Into for &GroupCoordinate { + fn into(self) -> leo_ast::GroupCoordinate { + use GroupCoordinate::*; + match self { + Number(value) => leo_ast::GroupCoordinate::Number(value.clone(), Default::default()), + SignHigh => leo_ast::GroupCoordinate::SignHigh, + SignLow => leo_ast::GroupCoordinate::SignLow, + Inferred => leo_ast::GroupCoordinate::Inferred, + } + } +} + +#[derive(Clone, Debug, PartialEq)] +pub enum GroupValue { + Single(String), + Tuple(GroupCoordinate, GroupCoordinate), +} + +#[derive(Clone, Debug, PartialEq)] +pub enum ConstValue { + Int(ConstInt), + Group(GroupValue), + Field(BigInt), + Address(String), + Boolean(bool), + + // compounds + Tuple(Vec), + Array(Vec), +} + +macro_rules! const_int_op { + ($name: ident, $retType: ty, $x: ident, $transform: expr) => { + pub fn $name(&self) -> $retType { + match self { + ConstInt::I8($x) => $transform, + ConstInt::I16($x) => $transform, + ConstInt::I32($x) => $transform, + ConstInt::I64($x) => $transform, + ConstInt::I128($x) => $transform, + ConstInt::U8($x) => $transform, + ConstInt::U16($x) => $transform, + ConstInt::U32($x) => $transform, + ConstInt::U64($x) => $transform, + ConstInt::U128($x) => $transform, + } + } + }; +} + +macro_rules! const_int_biop { + ($name: ident, $retType: ty, $x: ident, $y: ident, $transform: expr) => { + pub fn $name(&self, other: &ConstInt) -> Option<$retType> { + match (self, other) { + (ConstInt::I8($x), ConstInt::I8($y)) => $transform, + (ConstInt::I16($x), ConstInt::I16($y)) => $transform, + (ConstInt::I32($x), ConstInt::I32($y)) => $transform, + (ConstInt::I64($x), ConstInt::I64($y)) => $transform, + (ConstInt::I128($x), ConstInt::I128($y)) => $transform, + (ConstInt::U8($x), ConstInt::U8($y)) => $transform, + (ConstInt::U16($x), ConstInt::U16($y)) => $transform, + (ConstInt::U32($x), ConstInt::U32($y)) => $transform, + (ConstInt::U64($x), ConstInt::U64($y)) => $transform, + (ConstInt::U128($x), ConstInt::U128($y)) => $transform, + _ => None, + } + } + }; +} + +macro_rules! const_int_map { + ($name: ident, $x: ident, $transform: expr) => { + pub fn $name(&self) -> Option { + Some(match self { + ConstInt::I8($x) => ConstInt::I8($transform), + ConstInt::I16($x) => ConstInt::I16($transform), + ConstInt::I32($x) => ConstInt::I32($transform), + ConstInt::I64($x) => ConstInt::I64($transform), + ConstInt::I128($x) => ConstInt::I128($transform), + ConstInt::U8($x) => ConstInt::U8($transform), + ConstInt::U16($x) => ConstInt::U16($transform), + ConstInt::U32($x) => ConstInt::U32($transform), + ConstInt::U64($x) => ConstInt::U64($transform), + ConstInt::U128($x) => ConstInt::U128($transform), + }) + } + }; +} + +macro_rules! const_int_bimap { + ($name: ident, $x: ident, $y: ident, $transform: expr) => { + pub fn $name(&self, other: &ConstInt) -> Option { + Some(match (self, other) { + (ConstInt::I8($x), ConstInt::I8($y)) => ConstInt::I8($transform), + (ConstInt::I16($x), ConstInt::I16($y)) => ConstInt::I16($transform), + (ConstInt::I32($x), ConstInt::I32($y)) => ConstInt::I32($transform), + (ConstInt::I64($x), ConstInt::I64($y)) => ConstInt::I64($transform), + (ConstInt::I128($x), ConstInt::I128($y)) => ConstInt::I128($transform), + (ConstInt::U8($x), ConstInt::U8($y)) => ConstInt::U8($transform), + (ConstInt::U16($x), ConstInt::U16($y)) => ConstInt::U16($transform), + (ConstInt::U32($x), ConstInt::U32($y)) => ConstInt::U32($transform), + (ConstInt::U64($x), ConstInt::U64($y)) => ConstInt::U64($transform), + (ConstInt::U128($x), ConstInt::U128($y)) => ConstInt::U128($transform), + _ => return None, + }) + } + }; +} + +#[allow(clippy::useless_conversion)] +impl ConstInt { + const_int_op!(raw_value, String, x, format!("{}", x)); + + const_int_map!(value_negate, x, x.checked_neg()?); + + const_int_op!(to_usize, Option, x, (*x).try_into().ok()); + + const_int_op!(to_string, String, x, (*x).to_string()); + + const_int_bimap!(value_add, x, y, x.checked_add(*y)?); + + const_int_bimap!(value_sub, x, y, x.checked_sub(*y)?); + + const_int_bimap!(value_mul, x, y, x.checked_mul(*y)?); + + const_int_bimap!(value_div, x, y, x.checked_div(*y)?); + + // TODO: limited to 32 bit exponents + const_int_bimap!(value_pow, x, y, x.checked_pow((*y).try_into().ok()?)?); + + const_int_biop!(value_lt, bool, x, y, Some(x < y)); + + const_int_biop!(value_le, bool, x, y, Some(x <= y)); + + const_int_biop!(value_gt, bool, x, y, Some(x > y)); + + const_int_biop!(value_ge, bool, x, y, Some(x >= y)); + + pub fn get_int_type(&self) -> IntegerType { + match self { + ConstInt::I8(_) => IntegerType::I8, + ConstInt::I16(_) => IntegerType::I16, + ConstInt::I32(_) => IntegerType::I32, + ConstInt::I64(_) => IntegerType::I64, + ConstInt::I128(_) => IntegerType::I128, + ConstInt::U8(_) => IntegerType::U8, + ConstInt::U16(_) => IntegerType::U16, + ConstInt::U32(_) => IntegerType::U32, + ConstInt::U64(_) => IntegerType::U64, + ConstInt::U128(_) => IntegerType::U128, + } + } + + pub fn get_type(&self) -> Type { + Type::Integer(self.get_int_type()) + } + + pub fn parse(int_type: &IntegerType, value: &str, span: &Span) -> Result { + Ok(match int_type { + IntegerType::I8 => ConstInt::I8(value.parse().map_err(|_| AsgConvertError::invalid_int(&value, span))?), + IntegerType::I16 => ConstInt::I16(value.parse().map_err(|_| AsgConvertError::invalid_int(&value, span))?), + IntegerType::I32 => ConstInt::I32(value.parse().map_err(|_| AsgConvertError::invalid_int(&value, span))?), + IntegerType::I64 => ConstInt::I64(value.parse().map_err(|_| AsgConvertError::invalid_int(&value, span))?), + IntegerType::I128 => ConstInt::I128(value.parse().map_err(|_| AsgConvertError::invalid_int(&value, span))?), + IntegerType::U8 => ConstInt::U8(value.parse().map_err(|_| AsgConvertError::invalid_int(&value, span))?), + IntegerType::U16 => ConstInt::U16(value.parse().map_err(|_| AsgConvertError::invalid_int(&value, span))?), + IntegerType::U32 => ConstInt::U32(value.parse().map_err(|_| AsgConvertError::invalid_int(&value, span))?), + IntegerType::U64 => ConstInt::U64(value.parse().map_err(|_| AsgConvertError::invalid_int(&value, span))?), + IntegerType::U128 => ConstInt::U128(value.parse().map_err(|_| AsgConvertError::invalid_int(&value, span))?), + }) + } +} + +impl ConstValue { + pub fn get_type(&self) -> Option { + Some(match self { + ConstValue::Int(i) => i.get_type(), + ConstValue::Group(_) => Type::Group, + ConstValue::Field(_) => Type::Field, + ConstValue::Address(_) => Type::Address, + ConstValue::Boolean(_) => Type::Boolean, + ConstValue::Tuple(sub_consts) => { + Type::Tuple(sub_consts.iter().map(|x| x.get_type()).collect::>>()?) + } + ConstValue::Array(values) => Type::Array(Box::new(values.get(0)?.get_type()?), values.len()), + }) + } + + pub fn int(&self) -> Option<&ConstInt> { + match self { + ConstValue::Int(x) => Some(x), + _ => None, + } + } + + pub fn field(&self) -> Option<&BigInt> { + match self { + ConstValue::Field(x) => Some(x), + _ => None, + } + } +} diff --git a/asg/src/error/mod.rs b/asg/src/error/mod.rs new file mode 100644 index 0000000000..bebfada50b --- /dev/null +++ b/asg/src/error/mod.rs @@ -0,0 +1,274 @@ +// 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 . + +//! Errors encountered when attempting to convert to an asg from an ast. + +use crate::Span; +use leo_ast::{AstError, Error as FormattedError}; +use leo_grammar::ParserError; + +#[derive(Debug, Error)] +pub enum AsgConvertError { + #[error("{}", _0)] + AstError(#[from] AstError), + + #[error("{}", _0)] + Error(#[from] FormattedError), + + #[error("{}", _0)] + ImportError(FormattedError), + + #[error("{}", _0)] + InternalError(String), + + #[error("{}", _0)] + ParserError(#[from] ParserError), +} + +impl AsgConvertError { + fn new_from_span(message: String, span: &Span) -> Self { + AsgConvertError::Error(FormattedError::new_from_span(message, span.clone())) + } + + pub fn unresolved_circuit(name: &str, span: &Span) -> Self { + Self::new_from_span(format!("failed to resolve circuit: '{}'", name), span) + } + + pub fn unresolved_import(name: &str, span: &Span) -> Self { + Self::new_from_span(format!("failed to resolve import: '{}'", name), span) + } + + pub fn unresolved_circuit_member(circuit_name: &str, name: &str, span: &Span) -> Self { + Self::new_from_span( + format!( + "illegal reference to non-existant member '{}' of circuit '{}'", + name, circuit_name + ), + span, + ) + } + + pub fn missing_circuit_member(circuit_name: &str, name: &str, span: &Span) -> Self { + Self::new_from_span( + format!( + "missing circuit member '{}' for initialization of circuit '{}'", + name, circuit_name + ), + span, + ) + } + + pub fn overridden_circuit_member(circuit_name: &str, name: &str, span: &Span) -> Self { + Self::new_from_span( + format!( + "cannot declare circuit member '{}' more than once for initialization of circuit '{}'", + name, circuit_name + ), + span, + ) + } + + pub fn redefined_circuit_member(circuit_name: &str, name: &str, span: &Span) -> Self { + Self::new_from_span( + format!( + "cannot declare circuit member '{}' multiple times in circuit '{}'", + name, circuit_name + ), + span, + ) + } + + pub fn extra_circuit_member(circuit_name: &str, name: &str, span: &Span) -> Self { + Self::new_from_span( + format!( + "extra circuit member '{}' for initialization of circuit '{}' is not allowed", + name, circuit_name + ), + span, + ) + } + + pub fn illegal_function_assign(name: &str, span: &Span) -> Self { + Self::new_from_span(format!("attempt to assign to function '{}'", name), span) + } + + pub fn circuit_variable_call(circuit_name: &str, name: &str, span: &Span) -> Self { + Self::new_from_span( + format!("cannot call variable member '{}' of circuit '{}'", name, circuit_name), + span, + ) + } + + pub fn circuit_static_call_invalid(circuit_name: &str, name: &str, span: &Span) -> Self { + Self::new_from_span( + format!( + "cannot call static function '{}' of circuit '{}' from target", + name, circuit_name + ), + span, + ) + } + + pub fn circuit_member_mut_call_invalid(circuit_name: &str, name: &str, span: &Span) -> Self { + Self::new_from_span( + format!( + "cannot call mutable member function '{}' of circuit '{}' from immutable context", + name, circuit_name + ), + span, + ) + } + + pub fn circuit_member_call_invalid(circuit_name: &str, name: &str, span: &Span) -> Self { + Self::new_from_span( + format!( + "cannot call member function '{}' of circuit '{}' from static context", + name, circuit_name + ), + span, + ) + } + + pub fn circuit_function_ref(circuit_name: &str, name: &str, span: &Span) -> Self { + Self::new_from_span( + format!( + "cannot reference function member '{}' of circuit '{}' as value", + name, circuit_name + ), + span, + ) + } + + pub fn index_into_non_array(name: &str, span: &Span) -> Self { + Self::new_from_span(format!("failed to index into non-array '{}'", name), span) + } + + pub fn invalid_assign_index(name: &str, num: &str, span: &Span) -> Self { + Self::new_from_span( + format!("failed to index array with invalid integer '{}'[{}]", name, num), + span, + ) + } + + pub fn invalid_backwards_assignment(name: &str, left: usize, right: usize, span: &Span) -> Self { + Self::new_from_span( + format!( + "failed to index array range for assignment with left > right '{}'[{}..{}]", + name, left, right + ), + span, + ) + } + + pub fn index_into_non_tuple(name: &str, span: &Span) -> Self { + Self::new_from_span(format!("failed to index into non-tuple '{}'", name), span) + } + + pub fn tuple_index_out_of_bounds(index: usize, span: &Span) -> Self { + Self::new_from_span(format!("tuple index out of bounds: '{}'", index), span) + } + + pub fn unexpected_call_argument_count(expected: usize, got: usize, span: &Span) -> Self { + Self::new_from_span( + format!("function call expected {} arguments, got {}", expected, got), + span, + ) + } + + pub fn unresolved_function(name: &str, span: &Span) -> Self { + Self::new_from_span(format!("failed to resolve function: '{}'", name), span) + } + + pub fn unresolved_type(name: &str, span: &Span) -> Self { + Self::new_from_span( + format!("failed to resolve type for variable definition '{}'", name), + span, + ) + } + + pub fn unexpected_type(expected: &str, received: Option<&str>, span: &Span) -> Self { + // panic!(format!("unexpected type, expected: '{}', received: '{}'", expected, received.unwrap_or("unknown"))); + Self::new_from_span( + format!( + "unexpected type, expected: '{}', received: '{}'", + expected, + received.unwrap_or("unknown") + ), + span, + ) + } + + pub fn unexpected_nonconst(span: &Span) -> Self { + Self::new_from_span("expected const, found non-const value".to_string(), span) + } + + pub fn unresolved_reference(name: &str, span: &Span) -> Self { + Self::new_from_span(format!("failed to resolve variable reference '{}'", name), span) + } + + pub fn invalid_boolean(value: &str, span: &Span) -> Self { + Self::new_from_span(format!("failed to parse boolean value '{}'", value), span) + } + + pub fn invalid_int(value: &str, span: &Span) -> Self { + Self::new_from_span(format!("failed to parse int value '{}'", value), span) + } + + pub fn immutable_assignment(name: &str, span: &Span) -> Self { + Self::new_from_span(format!("illegal assignment to immutable variable '{}'", name), span) + } + + pub fn function_missing_return(name: &str, span: &Span) -> Self { + Self::new_from_span(format!("function '{}' missing return for all paths", name), span) + } + + pub fn function_return_validation(name: &str, description: &str, span: &Span) -> Self { + Self::new_from_span( + format!("function '{}' failed to validate return path: '{}'", name, description), + span, + ) + } + + pub fn input_ref_needs_type(category: &str, name: &str, span: &Span) -> Self { + Self::new_from_span( + format!("could not infer type for input in '{}': '{}'", category, name), + span, + ) + } + + pub fn invalid_self_in_global(span: &Span) -> Self { + Self::new_from_span( + "cannot have `mut self` or `self` arguments in global functions".to_string(), + span, + ) + } + + pub fn parse_index_error() -> Self { + AsgConvertError::InternalError("failed to parse index".to_string()) + } + + pub fn parse_dimension_error() -> Self { + AsgConvertError::InternalError("failed to parse dimension".to_string()) + } + + pub fn reference_self_outside_circuit() -> Self { + AsgConvertError::InternalError("referenced self outside of circuit function".to_string()) + } + + pub fn illegal_ast_structure(details: &str) -> Self { + AsgConvertError::InternalError(format!("illegal ast structure: {}", details)) + } +} diff --git a/asg/src/expression/array_access.rs b/asg/src/expression/array_access.rs new file mode 100644 index 0000000000..473601d412 --- /dev/null +++ b/asg/src/expression/array_access.rs @@ -0,0 +1,134 @@ +// 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 . + +use crate::{AsgConvertError, ConstValue, Expression, ExpressionNode, FromAst, Node, PartialType, Scope, Span, Type}; +use leo_ast::IntegerType; + +use std::{ + cell::RefCell, + sync::{Arc, Weak}, +}; + +pub struct ArrayAccessExpression { + pub parent: RefCell>>, + pub span: Option, + pub array: Arc, + pub index: Arc, +} + +impl Node for ArrayAccessExpression { + fn span(&self) -> Option<&Span> { + self.span.as_ref() + } +} + +impl ExpressionNode for ArrayAccessExpression { + fn set_parent(&self, parent: Weak) { + self.parent.replace(Some(parent)); + } + + fn get_parent(&self) -> Option> { + self.parent.borrow().as_ref().map(Weak::upgrade).flatten() + } + + fn enforce_parents(&self, expr: &Arc) { + self.array.set_parent(Arc::downgrade(expr)); + self.index.set_parent(Arc::downgrade(expr)); + } + + fn get_type(&self) -> Option { + match self.array.get_type() { + Some(Type::Array(element, _)) => Some(*element), + _ => None, + } + } + + fn is_mut_ref(&self) -> bool { + self.array.is_mut_ref() + } + + fn const_value(&self) -> Option { + let mut array = match self.array.const_value()? { + ConstValue::Array(values) => values, + _ => return None, + }; + let const_index = match self.index.const_value()? { + ConstValue::Int(x) => x.to_usize()?, + _ => return None, + }; + if const_index >= array.len() { + return None; + } + Some(array.remove(const_index)) + } + + fn is_consty(&self) -> bool { + self.array.is_consty() + } +} + +impl FromAst for ArrayAccessExpression { + fn from_ast( + scope: &Scope, + value: &leo_ast::ArrayAccessExpression, + expected_type: Option, + ) -> Result { + let array = Arc::::from_ast( + scope, + &*value.array, + Some(PartialType::Array(expected_type.map(Box::new), None)), + )?; + match array.get_type() { + Some(Type::Array(..)) => (), + type_ => { + return Err(AsgConvertError::unexpected_type( + "array", + type_.map(|x| x.to_string()).as_deref(), + &value.span, + )); + } + } + + let index = Arc::::from_ast( + scope, + &*value.index, + Some(PartialType::Integer(None, Some(IntegerType::U32))), + )?; + + if !index.is_consty() { + return Err(AsgConvertError::unexpected_nonconst( + &index.span().cloned().unwrap_or_default(), + )); + } + + Ok(ArrayAccessExpression { + parent: RefCell::new(None), + span: Some(value.span.clone()), + array, + index, + }) + } +} + +impl Into for &ArrayAccessExpression { + fn into(self) -> leo_ast::ArrayAccessExpression { + leo_ast::ArrayAccessExpression { + array: Box::new(self.array.as_ref().into()), + index: Box::new(self.index.as_ref().into()), + span: self.span.clone().unwrap_or_default(), + } + } +} diff --git a/asg/src/expression/array_init.rs b/asg/src/expression/array_init.rs new file mode 100644 index 0000000000..f7b9d5a95e --- /dev/null +++ b/asg/src/expression/array_init.rs @@ -0,0 +1,160 @@ +// 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 . + +use crate::{AsgConvertError, ConstValue, Expression, ExpressionNode, FromAst, Node, PartialType, Scope, Span, Type}; + +use std::{ + cell::RefCell, + sync::{Arc, Weak}, +}; + +pub struct ArrayInitExpression { + pub parent: RefCell>>, + pub span: Option, + pub element: Arc, + pub len: usize, +} + +impl Node for ArrayInitExpression { + fn span(&self) -> Option<&Span> { + self.span.as_ref() + } +} + +impl ExpressionNode for ArrayInitExpression { + fn set_parent(&self, parent: Weak) { + self.parent.replace(Some(parent)); + } + + fn get_parent(&self) -> Option> { + self.parent.borrow().as_ref().map(Weak::upgrade).flatten() + } + + fn enforce_parents(&self, expr: &Arc) { + self.element.set_parent(Arc::downgrade(expr)); + } + + fn get_type(&self) -> Option { + Some(Type::Array(Box::new(self.element.get_type()?), self.len)) + } + + fn is_mut_ref(&self) -> bool { + false + } + + fn const_value(&self) -> Option { + // not implemented due to performance concerns + None + } + + fn is_consty(&self) -> bool { + self.element.is_consty() + } +} + +impl FromAst for ArrayInitExpression { + fn from_ast( + scope: &Scope, + value: &leo_ast::ArrayInitExpression, + expected_type: Option, + ) -> Result { + let (mut expected_item, expected_len) = match expected_type { + Some(PartialType::Array(item, dims)) => (item.map(|x| *x), dims), + None => (None, None), + Some(type_) => { + return Err(AsgConvertError::unexpected_type( + &type_.to_string(), + Some("array"), + &value.span, + )); + } + }; + let dimensions = value + .dimensions + .0 + .iter() + .map(|x| { + x.value + .parse::() + .map_err(|_| AsgConvertError::parse_dimension_error()) + }) + .collect::, AsgConvertError>>()?; + + let len = *dimensions.get(0).ok_or_else(AsgConvertError::parse_dimension_error)?; + if let Some(expected_len) = expected_len { + if expected_len != len { + return Err(AsgConvertError::unexpected_type( + &*format!("array of length {}", expected_len), + Some(&*format!("array of length {}", len)), + &value.span, + )); + } + } + + for dimension in (&dimensions[1..]).iter().copied() { + expected_item = match expected_item { + Some(PartialType::Array(item, len)) => { + if let Some(len) = len { + if len != dimension { + return Err(AsgConvertError::unexpected_type( + &*format!("array of length {}", dimension), + Some(&*format!("array of length {}", len)), + &value.span, + )); + } + } + + item.map(|x| *x) + } + None => None, + Some(type_) => { + return Err(AsgConvertError::unexpected_type( + "array", + Some(&type_.to_string()), + &value.span, + )); + } + } + } + let mut element = Some(Arc::::from_ast(scope, &*value.element, expected_item)?); + let mut output = None; + + for dimension in dimensions.iter().rev().copied() { + output = Some(ArrayInitExpression { + parent: RefCell::new(None), + span: Some(value.span.clone()), + element: output + .map(Expression::ArrayInit) + .map(Arc::new) + .unwrap_or_else(|| element.take().unwrap()), + len: dimension, + }); + } + Ok(output.unwrap()) + } +} + +impl Into for &ArrayInitExpression { + fn into(self) -> leo_ast::ArrayInitExpression { + leo_ast::ArrayInitExpression { + element: Box::new(self.element.as_ref().into()), + dimensions: leo_ast::ArrayDimensions(vec![leo_ast::PositiveNumber { + value: self.len.to_string(), + }]), + span: self.span.clone().unwrap_or_default(), + } + } +} diff --git a/asg/src/expression/array_inline.rs b/asg/src/expression/array_inline.rs new file mode 100644 index 0000000000..274041c3e9 --- /dev/null +++ b/asg/src/expression/array_inline.rs @@ -0,0 +1,198 @@ +// 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 . + +use crate::{AsgConvertError, ConstValue, Expression, ExpressionNode, FromAst, Node, PartialType, Scope, Span, Type}; +use leo_ast::SpreadOrExpression; + +use std::{ + cell::RefCell, + sync::{Arc, Weak}, +}; + +pub struct ArrayInlineExpression { + pub parent: RefCell>>, + pub span: Option, + pub elements: Vec<(Arc, bool)>, // bool = if spread +} + +impl ArrayInlineExpression { + pub fn expanded_length(&self) -> usize { + self.elements + .iter() + .map(|(expr, is_spread)| { + if *is_spread { + match expr.get_type() { + Some(Type::Array(_item, len)) => len, + _ => 0, + } + } else { + 1 + } + }) + .sum() + } +} + +impl Node for ArrayInlineExpression { + fn span(&self) -> Option<&Span> { + self.span.as_ref() + } +} + +impl ExpressionNode for ArrayInlineExpression { + fn set_parent(&self, parent: Weak) { + self.parent.replace(Some(parent)); + } + + fn get_parent(&self) -> Option> { + self.parent.borrow().as_ref().map(Weak::upgrade).flatten() + } + + fn enforce_parents(&self, expr: &Arc) { + self.elements.iter().for_each(|(element, _)| { + element.set_parent(Arc::downgrade(expr)); + }) + } + + fn get_type(&self) -> Option { + Some(Type::Array( + Box::new(self.elements.first()?.0.get_type()?), + self.expanded_length(), + )) + } + + fn is_mut_ref(&self) -> bool { + false + } + + fn const_value(&self) -> Option { + let mut const_values = vec![]; + for (expr, spread) in self.elements.iter() { + if *spread { + match expr.const_value()? { + ConstValue::Array(items) => const_values.extend(items), + _ => return None, + } + } else { + const_values.push(expr.const_value()?); + } + } + Some(ConstValue::Array(const_values)) + } + + fn is_consty(&self) -> bool { + self.elements.iter().all(|x| x.0.is_consty()) + } +} + +impl FromAst for ArrayInlineExpression { + fn from_ast( + scope: &Scope, + value: &leo_ast::ArrayInlineExpression, + expected_type: Option, + ) -> Result { + let (mut expected_item, expected_len) = match expected_type { + Some(PartialType::Array(item, dims)) => (item.map(|x| *x), dims), + None => (None, None), + Some(type_) => { + return Err(AsgConvertError::unexpected_type( + &type_.to_string(), + Some("array"), + &value.span, + )); + } + }; + + let mut len = 0; + let output = ArrayInlineExpression { + parent: RefCell::new(None), + span: Some(value.span.clone()), + elements: value + .elements + .iter() + .map(|e| match e { + SpreadOrExpression::Expression(e) => { + let expr = Arc::::from_ast(scope, e, expected_item.clone())?; + if expected_item.is_none() { + expected_item = expr.get_type().map(Type::partial); + } + len += 1; + Ok((expr, false)) + } + SpreadOrExpression::Spread(e) => { + let expr = Arc::::from_ast( + scope, + e, + Some(PartialType::Array(expected_item.clone().map(Box::new), None)), + )?; + + match expr.get_type() { + Some(Type::Array(item, spread_len)) => { + if expected_item.is_none() { + expected_item = Some((*item).partial()); + } + + len += spread_len; + } + type_ => { + return Err(AsgConvertError::unexpected_type( + expected_item + .as_ref() + .map(|x| x.to_string()) + .as_deref() + .unwrap_or("unknown"), + type_.map(|x| x.to_string()).as_deref(), + &value.span, + )); + } + } + Ok((expr, true)) + } + }) + .collect::, AsgConvertError>>()?, + }; + if let Some(expected_len) = expected_len { + if len != expected_len { + return Err(AsgConvertError::unexpected_type( + &*format!("array of length {}", expected_len), + Some(&*format!("array of length {}", len)), + &value.span, + )); + } + } + Ok(output) + } +} + +impl Into for &ArrayInlineExpression { + fn into(self) -> leo_ast::ArrayInlineExpression { + leo_ast::ArrayInlineExpression { + elements: self + .elements + .iter() + .map(|(element, spread)| { + let element = element.as_ref().into(); + if *spread { + SpreadOrExpression::Spread(element) + } else { + SpreadOrExpression::Expression(element) + } + }) + .collect(), + span: self.span.clone().unwrap_or_default(), + } + } +} diff --git a/asg/src/expression/array_range_access.rs b/asg/src/expression/array_range_access.rs new file mode 100644 index 0000000000..666ff16729 --- /dev/null +++ b/asg/src/expression/array_range_access.rs @@ -0,0 +1,189 @@ +// 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 . + +use crate::{AsgConvertError, ConstValue, Expression, ExpressionNode, FromAst, Node, PartialType, Scope, Span, Type}; +use leo_ast::IntegerType; + +use std::{ + cell::RefCell, + sync::{Arc, Weak}, +}; + +pub struct ArrayRangeAccessExpression { + pub parent: RefCell>>, + pub span: Option, + pub array: Arc, + pub left: Option>, + pub right: Option>, +} + +impl Node for ArrayRangeAccessExpression { + fn span(&self) -> Option<&Span> { + self.span.as_ref() + } +} + +impl ExpressionNode for ArrayRangeAccessExpression { + fn set_parent(&self, parent: Weak) { + self.parent.replace(Some(parent)); + } + + fn get_parent(&self) -> Option> { + self.parent.borrow().as_ref().map(Weak::upgrade).flatten() + } + + fn enforce_parents(&self, expr: &Arc) { + self.array.set_parent(Arc::downgrade(expr)); + self.array.enforce_parents(&self.array); + if let Some(left) = self.left.as_ref() { + left.set_parent(Arc::downgrade(expr)); + } + if let Some(right) = self.right.as_ref() { + right.set_parent(Arc::downgrade(expr)); + } + } + + fn get_type(&self) -> Option { + let (element, array_len) = match self.array.get_type() { + Some(Type::Array(element, len)) => (element, len), + _ => return None, + }; + let const_left = match self.left.as_ref().map(|x| x.const_value()) { + Some(Some(ConstValue::Int(x))) => x.to_usize()?, + None => 0, + _ => return None, + }; + let const_right = match self.right.as_ref().map(|x| x.const_value()) { + Some(Some(ConstValue::Int(x))) => x.to_usize()?, + None => array_len, + _ => return None, + }; + if const_left > const_right || const_right > array_len { + return None; + } + + Some(Type::Array(element, const_right - const_left)) + } + + fn is_mut_ref(&self) -> bool { + self.array.is_mut_ref() + } + + fn const_value(&self) -> Option { + let mut array = match self.array.const_value()? { + ConstValue::Array(values) => values, + _ => return None, + }; + let const_left = match self.left.as_ref().map(|x| x.const_value()) { + Some(Some(ConstValue::Int(x))) => x.to_usize()?, + None => 0, + _ => return None, + }; + let const_right = match self.right.as_ref().map(|x| x.const_value()) { + Some(Some(ConstValue::Int(x))) => x.to_usize()?, + None => array.len(), + _ => return None, + }; + if const_left > const_right || const_right as usize > array.len() { + return None; + } + + Some(ConstValue::Array(array.drain(const_left..const_right).collect())) + } + + fn is_consty(&self) -> bool { + self.array.is_consty() + } +} + +impl FromAst for ArrayRangeAccessExpression { + fn from_ast( + scope: &Scope, + value: &leo_ast::ArrayRangeAccessExpression, + expected_type: Option, + ) -> Result { + let expected_array = match expected_type { + Some(PartialType::Array(element, _len)) => Some(PartialType::Array(element, None)), + None => None, + Some(x) => { + return Err(AsgConvertError::unexpected_type( + &x.to_string(), + Some("array"), + &value.span, + )); + } + }; + let array = Arc::::from_ast(scope, &*value.array, expected_array)?; + let array_type = array.get_type(); + match array_type { + Some(Type::Array(_, _)) => (), + type_ => { + return Err(AsgConvertError::unexpected_type( + "array", + type_.map(|x| x.to_string()).as_deref(), + &value.span, + )); + } + } + let left = value + .left + .as_deref() + .map(|left| { + Arc::::from_ast(scope, left, Some(PartialType::Integer(None, Some(IntegerType::U32)))) + }) + .transpose()?; + let right = value + .right + .as_deref() + .map(|right| { + Arc::::from_ast(scope, right, Some(PartialType::Integer(None, Some(IntegerType::U32)))) + }) + .transpose()?; + + if let Some(left) = left.as_ref() { + if !left.is_consty() { + return Err(AsgConvertError::unexpected_nonconst( + &left.span().cloned().unwrap_or_default(), + )); + } + } + if let Some(right) = right.as_ref() { + if !right.is_consty() { + return Err(AsgConvertError::unexpected_nonconst( + &right.span().cloned().unwrap_or_default(), + )); + } + } + Ok(ArrayRangeAccessExpression { + parent: RefCell::new(None), + span: Some(value.span.clone()), + array, + left, + right, + }) + } +} + +impl Into for &ArrayRangeAccessExpression { + fn into(self) -> leo_ast::ArrayRangeAccessExpression { + leo_ast::ArrayRangeAccessExpression { + array: Box::new(self.array.as_ref().into()), + left: self.left.as_ref().map(|left| Box::new(left.as_ref().into())), + right: self.right.as_ref().map(|right| Box::new(right.as_ref().into())), + span: self.span.clone().unwrap_or_default(), + } + } +} diff --git a/asg/src/expression/binary.rs b/asg/src/expression/binary.rs new file mode 100644 index 0000000000..bb19918471 --- /dev/null +++ b/asg/src/expression/binary.rs @@ -0,0 +1,262 @@ +// 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 . + +use crate::{AsgConvertError, ConstValue, Expression, ExpressionNode, FromAst, Node, PartialType, Scope, Span, Type}; +pub use leo_ast::{BinaryOperation, BinaryOperationClass}; + +use std::{ + cell::RefCell, + sync::{Arc, Weak}, +}; + +pub struct BinaryExpression { + pub parent: RefCell>>, + pub span: Option, + pub operation: BinaryOperation, + pub left: Arc, + pub right: Arc, +} + +impl Node for BinaryExpression { + fn span(&self) -> Option<&Span> { + self.span.as_ref() + } +} + +impl ExpressionNode for BinaryExpression { + fn set_parent(&self, parent: Weak) { + self.parent.replace(Some(parent)); + } + + fn get_parent(&self) -> Option> { + self.parent.borrow().as_ref().map(Weak::upgrade).flatten() + } + + fn enforce_parents(&self, expr: &Arc) { + self.left.set_parent(Arc::downgrade(expr)); + self.right.set_parent(Arc::downgrade(expr)); + } + + fn get_type(&self) -> Option { + match self.operation.class() { + BinaryOperationClass::Boolean => Some(Type::Boolean), + BinaryOperationClass::Numeric => self.left.get_type(), + } + } + + fn is_mut_ref(&self) -> bool { + false + } + + fn const_value(&self) -> Option { + use BinaryOperation::*; + let left = self.left.const_value()?; + let right = self.right.const_value()?; + + match (left, right) { + (ConstValue::Int(left), ConstValue::Int(right)) => Some(match self.operation { + Add => ConstValue::Int(left.value_add(&right)?), + Sub => ConstValue::Int(left.value_sub(&right)?), + Mul => ConstValue::Int(left.value_mul(&right)?), + Div => ConstValue::Int(left.value_div(&right)?), + Pow => ConstValue::Int(left.value_pow(&right)?), + Eq => ConstValue::Boolean(left == right), + Ne => ConstValue::Boolean(left != right), + Ge => ConstValue::Boolean(left.value_ge(&right)?), + Gt => ConstValue::Boolean(left.value_gt(&right)?), + Le => ConstValue::Boolean(left.value_le(&right)?), + Lt => ConstValue::Boolean(left.value_lt(&right)?), + _ => return None, + }), + // (ConstValue::Field(left), ConstValue::Field(right)) => { + // Some(match self.operation { + // Add => ConstValue::Field(left.checked_add(&right)?), + // Sub => ConstValue::Field(left.checked_sub(&right)?), + // Mul => ConstValue::Field(left.checked_mul(&right)?), + // Div => ConstValue::Field(left.checked_div(&right)?), + // Eq => ConstValue::Boolean(left == right), + // Ne => ConstValue::Boolean(left != right), + // _ => return None, + // }) + // }, + (ConstValue::Boolean(left), ConstValue::Boolean(right)) => Some(match self.operation { + Eq => ConstValue::Boolean(left == right), + Ne => ConstValue::Boolean(left != right), + And => ConstValue::Boolean(left && right), + Or => ConstValue::Boolean(left || right), + _ => return None, + }), + //todo: group? + (left, right) => Some(match self.operation { + Eq => ConstValue::Boolean(left == right), + Ne => ConstValue::Boolean(left != right), + _ => return None, + }), + } + } + + fn is_consty(&self) -> bool { + self.left.is_consty() && self.right.is_consty() + } +} + +impl FromAst for BinaryExpression { + fn from_ast( + scope: &Scope, + value: &leo_ast::BinaryExpression, + expected_type: Option, + ) -> Result { + let class = value.op.class(); + let expected_type = match class { + BinaryOperationClass::Boolean => match expected_type { + Some(PartialType::Type(Type::Boolean)) | None => None, + Some(x) => { + return Err(AsgConvertError::unexpected_type( + &x.to_string(), + Some(&*Type::Boolean.to_string()), + &value.span, + )); + } + }, + BinaryOperationClass::Numeric => match expected_type { + Some(x @ PartialType::Integer(_, _)) => Some(x), + Some(x) => { + return Err(AsgConvertError::unexpected_type( + &x.to_string(), + Some("integer"), + &value.span, + )); + } + None => None, + }, + }; + + // left + let (left, right) = match Arc::::from_ast(scope, &*value.left, expected_type.clone()) { + Ok(left) => { + if let Some(left_type) = left.get_type() { + let right = Arc::::from_ast(scope, &*value.right, Some(left_type.partial()))?; + (left, right) + } else { + let right = Arc::::from_ast(scope, &*value.right, expected_type)?; + if let Some(right_type) = right.get_type() { + ( + Arc::::from_ast(scope, &*value.left, Some(right_type.partial()))?, + right, + ) + } else { + (left, right) + } + } + } + Err(e) => { + let right = Arc::::from_ast(scope, &*value.right, expected_type)?; + if let Some(right_type) = right.get_type() { + ( + Arc::::from_ast(scope, &*value.left, Some(right_type.partial()))?, + right, + ) + } else { + return Err(e); + } + } + }; + + let left_type = left.get_type(); + #[allow(clippy::unused_unit)] + match class { + BinaryOperationClass::Numeric => match left_type { + Some(Type::Integer(_)) => (), + Some(Type::Group) | Some(Type::Field) + if value.op == BinaryOperation::Add || value.op == BinaryOperation::Sub => + { + () + } + Some(Type::Field) if value.op == BinaryOperation::Mul || value.op == BinaryOperation::Div => (), + type_ => { + return Err(AsgConvertError::unexpected_type( + "integer", + type_.map(|x| x.to_string()).as_deref(), + &value.span, + )); + } + }, + BinaryOperationClass::Boolean => match &value.op { + BinaryOperation::And | BinaryOperation::Or => match left_type { + Some(Type::Boolean) | None => (), + Some(x) => { + return Err(AsgConvertError::unexpected_type( + &x.to_string(), + Some(&*Type::Boolean.to_string()), + &value.span, + )); + } + }, + BinaryOperation::Eq | BinaryOperation::Ne => (), // all types allowed + _ => match left_type { + Some(Type::Integer(_)) | None => (), + Some(x) => { + return Err(AsgConvertError::unexpected_type( + &x.to_string(), + Some("integer"), + &value.span, + )); + } + }, + }, + } + + let right_type = right.get_type(); + + match (left_type, right_type) { + (Some(left_type), Some(right_type)) => { + if !left_type.is_assignable_from(&right_type) { + return Err(AsgConvertError::unexpected_type( + &left_type.to_string(), + Some(&*right_type.to_string()), + &value.span, + )); + } + } + (None, None) => { + return Err(AsgConvertError::unexpected_type( + "any type", + Some("unknown type"), + &value.span, + )); + } + (_, _) => (), + } + Ok(BinaryExpression { + parent: RefCell::new(None), + span: Some(value.span.clone()), + operation: value.op.clone(), + left, + right, + }) + } +} + +impl Into for &BinaryExpression { + fn into(self) -> leo_ast::BinaryExpression { + leo_ast::BinaryExpression { + op: self.operation.clone(), + left: Box::new(self.left.as_ref().into()), + right: Box::new(self.right.as_ref().into()), + span: self.span.clone().unwrap_or_default(), + } + } +} diff --git a/asg/src/expression/call.rs b/asg/src/expression/call.rs new file mode 100644 index 0000000000..c49a97c36f --- /dev/null +++ b/asg/src/expression/call.rs @@ -0,0 +1,244 @@ +// 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 . + +use crate::{ + AsgConvertError, + CircuitMember, + ConstValue, + Expression, + ExpressionNode, + FromAst, + Function, + FunctionQualifier, + Node, + PartialType, + Scope, + Span, + Type, +}; +pub use leo_ast::BinaryOperation; + +use std::{ + cell::RefCell, + sync::{Arc, Weak}, +}; + +pub struct CallExpression { + pub parent: RefCell>>, + pub span: Option, + pub function: Arc, + pub target: Option>, + pub arguments: Vec>, +} + +impl Node for CallExpression { + fn span(&self) -> Option<&Span> { + self.span.as_ref() + } +} + +impl ExpressionNode for CallExpression { + fn set_parent(&self, parent: Weak) { + self.parent.replace(Some(parent)); + } + + fn get_parent(&self) -> Option> { + self.parent.borrow().as_ref().map(Weak::upgrade).flatten() + } + + fn enforce_parents(&self, expr: &Arc) { + if let Some(target) = self.target.as_ref() { + target.set_parent(Arc::downgrade(expr)); + } + self.arguments.iter().for_each(|element| { + element.set_parent(Arc::downgrade(expr)); + }) + } + + fn get_type(&self) -> Option { + Some(self.function.output.clone().into()) + } + + fn is_mut_ref(&self) -> bool { + false + } + + fn const_value(&self) -> Option { + // static function const evaluation + None + } + + fn is_consty(&self) -> bool { + self.target.as_ref().map(|x| x.is_consty()).unwrap_or(true) && self.arguments.iter().all(|x| x.is_consty()) + } +} + +impl FromAst for CallExpression { + fn from_ast( + scope: &Scope, + value: &leo_ast::CallExpression, + expected_type: Option, + ) -> Result { + let (target, function) = match &*value.function { + leo_ast::Expression::Identifier(name) => ( + None, + scope + .borrow() + .resolve_function(&name.name) + .ok_or_else(|| AsgConvertError::unresolved_function(&name.name, &name.span))?, + ), + leo_ast::Expression::CircuitMemberAccess(leo_ast::CircuitMemberAccessExpression { + circuit: ast_circuit, + name, + span, + }) => { + let target = Arc::::from_ast(scope, &**ast_circuit, None)?; + let circuit = match target.get_type() { + Some(Type::Circuit(circuit)) => circuit, + type_ => { + return Err(AsgConvertError::unexpected_type( + "circuit", + type_.map(|x| x.to_string()).as_deref(), + &span, + )); + } + }; + let circuit_name = circuit.name.borrow().name.clone(); + let member = circuit.members.borrow(); + let member = member + .get(&name.name) + .ok_or_else(|| AsgConvertError::unresolved_circuit_member(&circuit_name, &name.name, &span))?; + match member { + CircuitMember::Function(body) => { + if body.qualifier == FunctionQualifier::Static { + return Err(AsgConvertError::circuit_static_call_invalid( + &circuit_name, + &name.name, + &span, + )); + } else if body.qualifier == FunctionQualifier::MutSelfRef && !target.is_mut_ref() { + return Err(AsgConvertError::circuit_member_mut_call_invalid( + &circuit_name, + &name.name, + &span, + )); + } + (Some(target), body.clone()) + } + CircuitMember::Variable(_) => { + return Err(AsgConvertError::circuit_variable_call(&circuit_name, &name.name, &span)); + } + } + } + leo_ast::Expression::CircuitStaticFunctionAccess(leo_ast::CircuitStaticFunctionAccessExpression { + circuit: ast_circuit, + name, + span, + }) => { + let circuit = if let leo_ast::Expression::Identifier(circuit_name) = &**ast_circuit { + scope + .borrow() + .resolve_circuit(&circuit_name.name) + .ok_or_else(|| AsgConvertError::unresolved_circuit(&circuit_name.name, &circuit_name.span))? + } else { + return Err(AsgConvertError::unexpected_type("circuit", None, &span)); + }; + let circuit_name = circuit.name.borrow().name.clone(); + + let member = circuit.members.borrow(); + let member = member + .get(&name.name) + .ok_or_else(|| AsgConvertError::unresolved_circuit_member(&circuit_name, &name.name, &span))?; + match member { + CircuitMember::Function(body) => { + if body.qualifier != FunctionQualifier::Static { + return Err(AsgConvertError::circuit_member_call_invalid( + &circuit_name, + &name.name, + &span, + )); + } + (None, body.clone()) + } + CircuitMember::Variable(_) => { + return Err(AsgConvertError::circuit_variable_call(&circuit_name, &name.name, &span)); + } + } + } + _ => { + return Err(AsgConvertError::illegal_ast_structure( + "non Identifier/CircuitMemberAccess/CircuitStaticFunctionAccess as call target", + )); + } + }; + if let Some(expected) = expected_type { + let output: Type = function.output.clone().into(); + if !expected.matches(&output) { + return Err(AsgConvertError::unexpected_type( + &expected.to_string(), + Some(&*output.to_string()), + &value.span, + )); + } + } + if value.arguments.len() != function.argument_types.len() { + return Err(AsgConvertError::unexpected_call_argument_count( + function.argument_types.len(), + value.arguments.len(), + &value.span, + )); + } + + Ok(CallExpression { + parent: RefCell::new(None), + span: Some(value.span.clone()), + arguments: value + .arguments + .iter() + .zip(function.argument_types.iter()) + .map(|(expr, argument)| { + Arc::::from_ast(scope, expr, Some(argument.clone().strong().partial())) + }) + .collect::, AsgConvertError>>()?, + function, + target, + }) + } +} + +impl Into for &CallExpression { + fn into(self) -> leo_ast::CallExpression { + let target_function = if let Some(target) = &self.target { + target.as_ref().into() + } else { + let circuit = self.function.circuit.borrow().as_ref().map(|x| x.upgrade()).flatten(); + if let Some(circuit) = circuit { + leo_ast::Expression::CircuitStaticFunctionAccess(leo_ast::CircuitStaticFunctionAccessExpression { + circuit: Box::new(leo_ast::Expression::Identifier(circuit.name.borrow().clone())), + name: self.function.name.borrow().clone(), + span: self.span.clone().unwrap_or_default(), + }) + } else { + leo_ast::Expression::Identifier(self.function.name.borrow().clone()) + } + }; + leo_ast::CallExpression { + function: Box::new(target_function), + arguments: self.arguments.iter().map(|arg| arg.as_ref().into()).collect(), + span: self.span.clone().unwrap_or_default(), + } + } +} diff --git a/asg/src/expression/circuit_access.rs b/asg/src/expression/circuit_access.rs new file mode 100644 index 0000000000..b1eba2b84c --- /dev/null +++ b/asg/src/expression/circuit_access.rs @@ -0,0 +1,256 @@ +// 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 . + +// 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 . + +use crate::{ + AsgConvertError, + Circuit, + CircuitMember, + CircuitMemberBody, + ConstValue, + Expression, + ExpressionNode, + FromAst, + Identifier, + Node, + PartialType, + Scope, + Span, + Type, +}; + +use std::{ + cell::RefCell, + sync::{Arc, Weak}, +}; + +pub struct CircuitAccessExpression { + pub parent: RefCell>>, + pub span: Option, + pub circuit: Arc, + pub target: Option>, + pub member: Identifier, +} + +impl Node for CircuitAccessExpression { + fn span(&self) -> Option<&Span> { + self.span.as_ref() + } +} + +impl ExpressionNode for CircuitAccessExpression { + fn set_parent(&self, parent: Weak) { + self.parent.replace(Some(parent)); + } + + fn get_parent(&self) -> Option> { + self.parent.borrow().as_ref().map(Weak::upgrade).flatten() + } + + fn enforce_parents(&self, expr: &Arc) { + if let Some(target) = self.target.as_ref() { + target.set_parent(Arc::downgrade(expr)); + } + } + + fn get_type(&self) -> Option { + if self.target.is_none() { + None // function target only for static + } else { + let members = self.circuit.members.borrow(); + let member = members.get(&self.member.name)?; + match member { + CircuitMember::Variable(type_) => Some(type_.clone().into()), + CircuitMember::Function(_) => None, + } + } + } + + fn is_mut_ref(&self) -> bool { + if let Some(target) = self.target.as_ref() { + target.is_mut_ref() + } else { + false + } + } + + fn const_value(&self) -> Option { + None + } + + fn is_consty(&self) -> bool { + self.target.as_ref().map(|x| x.is_consty()).unwrap_or(true) + } +} + +impl FromAst for CircuitAccessExpression { + fn from_ast( + scope: &Scope, + value: &leo_ast::CircuitMemberAccessExpression, + expected_type: Option, + ) -> Result { + let target = Arc::::from_ast(scope, &*value.circuit, None)?; + let circuit = match target.get_type() { + Some(Type::Circuit(circuit)) => circuit, + x => { + return Err(AsgConvertError::unexpected_type( + "circuit", + x.map(|x| x.to_string()).as_deref(), + &value.span, + )); + } + }; + + // scoping refcell reference + let found_member = { + if let Some(member) = circuit.members.borrow().get(&value.name.name) { + if let Some(expected_type) = &expected_type { + if let CircuitMember::Variable(type_) = &member { + let type_: Type = type_.clone().into(); + if !expected_type.matches(&type_) { + return Err(AsgConvertError::unexpected_type( + &expected_type.to_string(), + Some(&type_.to_string()), + &value.span, + )); + } + } // used by call expression + } + true + } else { + false + } + }; + + if found_member { + // skip + } else if circuit.is_input_pseudo_circuit() { + // add new member to implicit input + if let Some(expected_type) = expected_type.map(PartialType::full).flatten() { + circuit.members.borrow_mut().insert( + value.name.name.clone(), + CircuitMember::Variable(expected_type.clone().into()), + ); + let body = circuit.body.borrow().upgrade().expect("stale input circuit body"); + + body.members + .borrow_mut() + .insert(value.name.name.clone(), CircuitMemberBody::Variable(expected_type)); + } else { + return Err(AsgConvertError::input_ref_needs_type( + &circuit.name.borrow().name, + &value.name.name, + &value.span, + )); + } + } else { + return Err(AsgConvertError::unresolved_circuit_member( + &circuit.name.borrow().name, + &value.name.name, + &value.span, + )); + } + + Ok(CircuitAccessExpression { + parent: RefCell::new(None), + span: Some(value.span.clone()), + target: Some(target), + circuit, + member: value.name.clone(), + }) + } +} + +impl FromAst for CircuitAccessExpression { + fn from_ast( + scope: &Scope, + value: &leo_ast::CircuitStaticFunctionAccessExpression, + expected_type: Option, + ) -> Result { + let circuit = match &*value.circuit { + leo_ast::Expression::Identifier(name) => scope + .borrow() + .resolve_circuit(&name.name) + .ok_or_else(|| AsgConvertError::unresolved_circuit(&name.name, &name.span))?, + _ => { + return Err(AsgConvertError::unexpected_type( + "circuit", + Some("unknown"), + &value.span, + )); + } + }; + + if let Some(expected_type) = expected_type { + return Err(AsgConvertError::unexpected_type( + &expected_type.to_string(), + Some("none"), + &value.span, + )); + } + + if let Some(CircuitMember::Function(_)) = circuit.members.borrow().get(&value.name.name) { + // okay + } else { + return Err(AsgConvertError::unresolved_circuit_member( + &circuit.name.borrow().name, + &value.name.name, + &value.span, + )); + } + + Ok(CircuitAccessExpression { + parent: RefCell::new(None), + span: Some(value.span.clone()), + target: None, + circuit, + member: value.name.clone(), + }) + } +} + +impl Into for &CircuitAccessExpression { + fn into(self) -> leo_ast::Expression { + if let Some(target) = self.target.as_ref() { + leo_ast::Expression::CircuitMemberAccess(leo_ast::CircuitMemberAccessExpression { + circuit: Box::new(target.as_ref().into()), + name: self.member.clone(), + span: self.span.clone().unwrap_or_default(), + }) + } else { + leo_ast::Expression::CircuitStaticFunctionAccess(leo_ast::CircuitStaticFunctionAccessExpression { + circuit: Box::new(leo_ast::Expression::Identifier(self.circuit.name.borrow().clone())), + name: self.member.clone(), + span: self.span.clone().unwrap_or_default(), + }) + } + } +} diff --git a/asg/src/expression/circuit_init.rs b/asg/src/expression/circuit_init.rs new file mode 100644 index 0000000000..b9309b307a --- /dev/null +++ b/asg/src/expression/circuit_init.rs @@ -0,0 +1,177 @@ +// 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 . + +use crate::{ + AsgConvertError, + Circuit, + CircuitMember, + ConstValue, + Expression, + ExpressionNode, + FromAst, + Identifier, + Node, + PartialType, + Scope, + Span, + Type, +}; + +use indexmap::{IndexMap, IndexSet}; +use std::{ + cell::RefCell, + sync::{Arc, Weak}, +}; + +pub struct CircuitInitExpression { + pub parent: RefCell>>, + pub span: Option, + pub circuit: Arc, + pub values: Vec<(Identifier, Arc)>, +} + +impl Node for CircuitInitExpression { + fn span(&self) -> Option<&Span> { + self.span.as_ref() + } +} + +impl ExpressionNode for CircuitInitExpression { + fn set_parent(&self, parent: Weak) { + self.parent.replace(Some(parent)); + } + + fn get_parent(&self) -> Option> { + self.parent.borrow().as_ref().map(Weak::upgrade).flatten() + } + + fn enforce_parents(&self, expr: &Arc) { + self.values.iter().for_each(|(_, element)| { + element.set_parent(Arc::downgrade(expr)); + }) + } + + fn get_type(&self) -> Option { + Some(Type::Circuit(self.circuit.clone())) + } + + fn is_mut_ref(&self) -> bool { + false + } + + fn const_value(&self) -> Option { + None + } + + fn is_consty(&self) -> bool { + self.values.iter().all(|(_, value)| value.is_consty()) + } +} + +impl FromAst for CircuitInitExpression { + fn from_ast( + scope: &Scope, + value: &leo_ast::CircuitInitExpression, + expected_type: Option, + ) -> Result { + let circuit = scope + .borrow() + .resolve_circuit(&value.name.name) + .ok_or_else(|| AsgConvertError::unresolved_circuit(&value.name.name, &value.name.span))?; + match expected_type { + Some(PartialType::Type(Type::Circuit(expected_circuit))) if expected_circuit == circuit => (), + None => (), + Some(x) => { + return Err(AsgConvertError::unexpected_type( + &x.to_string(), + Some(&circuit.name.borrow().name), + &value.span, + )); + } + } + let members: IndexMap<&String, (&Identifier, &leo_ast::Expression)> = value + .members + .iter() + .map(|x| (&x.identifier.name, (&x.identifier, &x.expression))) + .collect(); + + let mut values: Vec<(Identifier, Arc)> = vec![]; + let mut defined_variables = IndexSet::::new(); + + { + let circuit_members = circuit.members.borrow(); + for (name, member) in circuit_members.iter() { + if defined_variables.contains(name) { + return Err(AsgConvertError::overridden_circuit_member( + &circuit.name.borrow().name, + name, + &value.span, + )); + } + defined_variables.insert(name.clone()); + let type_: Type = if let CircuitMember::Variable(type_) = &member { + type_.clone().into() + } else { + continue; + }; + if let Some((identifier, receiver)) = members.get(&name) { + let received = Arc::::from_ast(scope, *receiver, Some(type_.partial()))?; + values.push(((*identifier).clone(), received)); + } else { + return Err(AsgConvertError::missing_circuit_member( + &circuit.name.borrow().name, + name, + &value.span, + )); + } + } + + for (name, (identifier, _expression)) in members.iter() { + if circuit_members.get(*name).is_none() { + return Err(AsgConvertError::extra_circuit_member( + &circuit.name.borrow().name, + *name, + &identifier.span, + )); + } + } + } + + Ok(CircuitInitExpression { + parent: RefCell::new(None), + span: Some(value.span.clone()), + circuit, + values, + }) + } +} + +impl Into for &CircuitInitExpression { + fn into(self) -> leo_ast::CircuitInitExpression { + leo_ast::CircuitInitExpression { + name: self.circuit.name.borrow().clone(), + members: self + .values + .iter() + .map(|(name, value)| leo_ast::CircuitVariableDefinition { + identifier: name.clone(), + expression: value.as_ref().into(), + }) + .collect(), + span: self.span.clone().unwrap_or_default(), + } + } +} diff --git a/asg/src/expression/constant.rs b/asg/src/expression/constant.rs new file mode 100644 index 0000000000..9ec9cb7036 --- /dev/null +++ b/asg/src/expression/constant.rs @@ -0,0 +1,237 @@ +// 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 . + +use crate::{ + AsgConvertError, + ConstInt, + ConstValue, + Expression, + ExpressionNode, + FromAst, + GroupValue, + Node, + PartialType, + Scope, + Span, + Type, +}; + +use std::{ + cell::RefCell, + sync::{Arc, Weak}, +}; + +pub struct Constant { + pub parent: RefCell>>, + pub span: Option, + pub value: ConstValue, // should not be compound constants +} + +impl Node for Constant { + fn span(&self) -> Option<&Span> { + self.span.as_ref() + } +} + +impl ExpressionNode for Constant { + fn set_parent(&self, parent: Weak) { + self.parent.replace(Some(parent)); + } + + fn get_parent(&self) -> Option> { + self.parent.borrow().as_ref().map(Weak::upgrade).flatten() + } + + fn enforce_parents(&self, _expr: &Arc) {} + + fn get_type(&self) -> Option { + self.value.get_type() + } + + fn is_mut_ref(&self) -> bool { + false + } + + fn const_value(&self) -> Option { + Some(self.value.clone()) + } + + fn is_consty(&self) -> bool { + true + } +} + +impl FromAst for Constant { + fn from_ast( + _scope: &Scope, + value: &leo_ast::ValueExpression, + expected_type: Option, + ) -> Result { + use leo_ast::ValueExpression::*; + Ok(match value { + Address(value, span) => { + match expected_type.map(PartialType::full).flatten() { + Some(Type::Address) | None => (), + Some(x) => { + return Err(AsgConvertError::unexpected_type( + &x.to_string(), + Some(&*Type::Address.to_string()), + span, + )); + } + } + Constant { + parent: RefCell::new(None), + span: Some(span.clone()), + value: ConstValue::Address(value.clone()), + } + } + Boolean(value, span) => { + match expected_type.map(PartialType::full).flatten() { + Some(Type::Boolean) | None => (), + Some(x) => { + return Err(AsgConvertError::unexpected_type( + &x.to_string(), + Some(&*Type::Boolean.to_string()), + span, + )); + } + } + Constant { + parent: RefCell::new(None), + span: Some(span.clone()), + value: ConstValue::Boolean( + value + .parse::() + .map_err(|_| AsgConvertError::invalid_boolean(&value, span))?, + ), + } + } + Field(value, span) => { + match expected_type.map(PartialType::full).flatten() { + Some(Type::Field) | None => (), + Some(x) => { + return Err(AsgConvertError::unexpected_type( + &x.to_string(), + Some(&*Type::Field.to_string()), + span, + )); + } + } + Constant { + parent: RefCell::new(None), + span: Some(span.clone()), + value: ConstValue::Field(value.parse().map_err(|_| AsgConvertError::invalid_int(&value, span))?), + } + } + Group(value) => { + match expected_type.map(PartialType::full).flatten() { + Some(Type::Group) | None => (), + Some(x) => { + return Err(AsgConvertError::unexpected_type( + &x.to_string(), + Some(&*Type::Group.to_string()), + value.span(), + )); + } + } + Constant { + parent: RefCell::new(None), + span: Some(value.span().clone()), + value: ConstValue::Group(match &**value { + leo_ast::GroupValue::Single(value, _) => GroupValue::Single(value.clone()), + leo_ast::GroupValue::Tuple(leo_ast::GroupTuple { x, y, .. }) => { + GroupValue::Tuple(x.into(), y.into()) + } + }), + } + } + Implicit(value, span) => match expected_type { + None => return Err(AsgConvertError::unresolved_type("unknown", span)), + Some(PartialType::Integer(Some(sub_type), _)) | Some(PartialType::Integer(None, Some(sub_type))) => { + Constant { + parent: RefCell::new(None), + span: Some(span.clone()), + value: ConstValue::Int(ConstInt::parse(&sub_type, value, span)?), + } + } + Some(PartialType::Type(Type::Field)) => Constant { + parent: RefCell::new(None), + span: Some(span.clone()), + value: ConstValue::Field(value.parse().map_err(|_| AsgConvertError::invalid_int(&value, span))?), + }, + Some(PartialType::Type(Type::Address)) => Constant { + parent: RefCell::new(None), + span: Some(span.clone()), + value: ConstValue::Address(value.to_string()), + }, + Some(x) => return Err(AsgConvertError::unexpected_type(&x.to_string(), Some("unknown"), span)), + }, + Integer(int_type, value, span) => { + match expected_type { + Some(PartialType::Integer(Some(sub_type), _)) if &sub_type == int_type => (), + Some(PartialType::Integer(None, Some(_))) => (), + None => (), + Some(x) => { + return Err(AsgConvertError::unexpected_type( + &x.to_string(), + Some(&*int_type.to_string()), + span, + )); + } + } + Constant { + parent: RefCell::new(None), + span: Some(span.clone()), + value: ConstValue::Int(ConstInt::parse(int_type, value, span)?), + } + } + }) + } +} + +impl Into for &Constant { + fn into(self) -> leo_ast::ValueExpression { + match &self.value { + ConstValue::Address(value) => { + leo_ast::ValueExpression::Address(value.clone(), self.span.clone().unwrap_or_default()) + } + ConstValue::Boolean(value) => { + leo_ast::ValueExpression::Boolean(value.to_string(), self.span.clone().unwrap_or_default()) + } + ConstValue::Field(value) => { + leo_ast::ValueExpression::Field(value.to_string(), self.span.clone().unwrap_or_default()) + } + ConstValue::Group(value) => leo_ast::ValueExpression::Group(Box::new(match value { + GroupValue::Single(single) => { + leo_ast::GroupValue::Single(single.clone(), self.span.clone().unwrap_or_default()) + } + GroupValue::Tuple(left, right) => leo_ast::GroupValue::Tuple(leo_ast::GroupTuple { + x: left.into(), + y: right.into(), + span: self.span.clone().unwrap_or_default(), + }), + })), + ConstValue::Int(int) => leo_ast::ValueExpression::Integer( + int.get_int_type(), + int.raw_value(), + self.span.clone().unwrap_or_default(), + ), + ConstValue::Tuple(_) => unimplemented!(), + ConstValue::Array(_) => unimplemented!(), + } + } +} diff --git a/asg/src/expression/mod.rs b/asg/src/expression/mod.rs new file mode 100644 index 0000000000..fb21c16039 --- /dev/null +++ b/asg/src/expression/mod.rs @@ -0,0 +1,343 @@ +// 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 . + +//! This module defines an expression node in an asg. +//! +//! Notable differences after conversion from an ast expression include: +//! 1. Storing variable references instead of variable identifiers - better history tracking and mutability +//! 2. Resolving constant values - optimizes execution of program circuit. + +mod array_access; +pub use array_access::*; + +mod array_inline; +pub use array_inline::*; + +mod array_init; +pub use array_init::*; + +mod array_range_access; +pub use array_range_access::*; + +mod binary; +pub use binary::*; + +mod call; +pub use call::*; + +mod circuit_access; +pub use circuit_access::*; + +mod circuit_init; +pub use circuit_init::*; + +mod constant; +pub use constant::*; + +mod ternary; +pub use ternary::*; + +mod tuple_access; +pub use tuple_access::*; + +mod tuple_init; +pub use tuple_init::*; + +mod unary; +pub use unary::*; + +mod variable_ref; +pub use variable_ref::*; + +use crate::{AsgConvertError, ConstValue, FromAst, Node, PartialType, Scope, Span, Type}; + +use std::sync::{Arc, Weak}; + +pub enum Expression { + VariableRef(VariableRef), + Constant(Constant), + Binary(BinaryExpression), + Unary(UnaryExpression), + Ternary(TernaryExpression), + + ArrayInline(ArrayInlineExpression), + ArrayInit(ArrayInitExpression), + ArrayAccess(ArrayAccessExpression), + ArrayRangeAccess(ArrayRangeAccessExpression), + + TupleInit(TupleInitExpression), + TupleAccess(TupleAccessExpression), + + CircuitInit(CircuitInitExpression), + CircuitAccess(CircuitAccessExpression), + + Call(CallExpression), +} + +impl Node for Expression { + fn span(&self) -> Option<&Span> { + use Expression::*; + match self { + VariableRef(x) => x.span(), + Constant(x) => x.span(), + Binary(x) => x.span(), + Unary(x) => x.span(), + Ternary(x) => x.span(), + ArrayInline(x) => x.span(), + ArrayInit(x) => x.span(), + ArrayAccess(x) => x.span(), + ArrayRangeAccess(x) => x.span(), + TupleInit(x) => x.span(), + TupleAccess(x) => x.span(), + CircuitInit(x) => x.span(), + CircuitAccess(x) => x.span(), + Call(x) => x.span(), + } + } +} + +pub trait ExpressionNode: Node { + fn set_parent(&self, parent: Weak); + fn get_parent(&self) -> Option>; + fn enforce_parents(&self, expr: &Arc); + + fn get_type(&self) -> Option; + fn is_mut_ref(&self) -> bool; + fn const_value(&self) -> Option; // todo: memoize + fn is_consty(&self) -> bool; +} + +impl ExpressionNode for Expression { + fn set_parent(&self, parent: Weak) { + use Expression::*; + match self { + VariableRef(x) => x.set_parent(parent), + Constant(x) => x.set_parent(parent), + Binary(x) => x.set_parent(parent), + Unary(x) => x.set_parent(parent), + Ternary(x) => x.set_parent(parent), + ArrayInline(x) => x.set_parent(parent), + ArrayInit(x) => x.set_parent(parent), + ArrayAccess(x) => x.set_parent(parent), + ArrayRangeAccess(x) => x.set_parent(parent), + TupleInit(x) => x.set_parent(parent), + TupleAccess(x) => x.set_parent(parent), + CircuitInit(x) => x.set_parent(parent), + CircuitAccess(x) => x.set_parent(parent), + Call(x) => x.set_parent(parent), + } + } + + fn get_parent(&self) -> Option> { + use Expression::*; + match self { + VariableRef(x) => x.get_parent(), + Constant(x) => x.get_parent(), + Binary(x) => x.get_parent(), + Unary(x) => x.get_parent(), + Ternary(x) => x.get_parent(), + ArrayInline(x) => x.get_parent(), + ArrayInit(x) => x.get_parent(), + ArrayAccess(x) => x.get_parent(), + ArrayRangeAccess(x) => x.get_parent(), + TupleInit(x) => x.get_parent(), + TupleAccess(x) => x.get_parent(), + CircuitInit(x) => x.get_parent(), + CircuitAccess(x) => x.get_parent(), + Call(x) => x.get_parent(), + } + } + + fn enforce_parents(&self, expr: &Arc) { + use Expression::*; + match self { + VariableRef(x) => x.enforce_parents(expr), + Constant(x) => x.enforce_parents(expr), + Binary(x) => x.enforce_parents(expr), + Unary(x) => x.enforce_parents(expr), + Ternary(x) => x.enforce_parents(expr), + ArrayInline(x) => x.enforce_parents(expr), + ArrayInit(x) => x.enforce_parents(expr), + ArrayAccess(x) => x.enforce_parents(expr), + ArrayRangeAccess(x) => x.enforce_parents(expr), + TupleInit(x) => x.enforce_parents(expr), + TupleAccess(x) => x.enforce_parents(expr), + CircuitInit(x) => x.enforce_parents(expr), + CircuitAccess(x) => x.enforce_parents(expr), + Call(x) => x.enforce_parents(expr), + } + } + + fn get_type(&self) -> Option { + use Expression::*; + match self { + VariableRef(x) => x.get_type(), + Constant(x) => x.get_type(), + Binary(x) => x.get_type(), + Unary(x) => x.get_type(), + Ternary(x) => x.get_type(), + ArrayInline(x) => x.get_type(), + ArrayInit(x) => x.get_type(), + ArrayAccess(x) => x.get_type(), + ArrayRangeAccess(x) => x.get_type(), + TupleInit(x) => x.get_type(), + TupleAccess(x) => x.get_type(), + CircuitInit(x) => x.get_type(), + CircuitAccess(x) => x.get_type(), + Call(x) => x.get_type(), + } + } + + fn is_mut_ref(&self) -> bool { + use Expression::*; + match self { + VariableRef(x) => x.is_mut_ref(), + Constant(x) => x.is_mut_ref(), + Binary(x) => x.is_mut_ref(), + Unary(x) => x.is_mut_ref(), + Ternary(x) => x.is_mut_ref(), + ArrayInline(x) => x.is_mut_ref(), + ArrayInit(x) => x.is_mut_ref(), + ArrayAccess(x) => x.is_mut_ref(), + ArrayRangeAccess(x) => x.is_mut_ref(), + TupleInit(x) => x.is_mut_ref(), + TupleAccess(x) => x.is_mut_ref(), + CircuitInit(x) => x.is_mut_ref(), + CircuitAccess(x) => x.is_mut_ref(), + Call(x) => x.is_mut_ref(), + } + } + + fn const_value(&self) -> Option { + use Expression::*; + match self { + VariableRef(x) => x.const_value(), + Constant(x) => x.const_value(), + Binary(x) => x.const_value(), + Unary(x) => x.const_value(), + Ternary(x) => x.const_value(), + ArrayInline(x) => x.const_value(), + ArrayInit(x) => x.const_value(), + ArrayAccess(x) => x.const_value(), + ArrayRangeAccess(x) => x.const_value(), + TupleInit(x) => x.const_value(), + TupleAccess(x) => x.const_value(), + CircuitInit(x) => x.const_value(), + CircuitAccess(x) => x.const_value(), + Call(x) => x.const_value(), + } + } + + fn is_consty(&self) -> bool { + use Expression::*; + match self { + VariableRef(x) => x.is_consty(), + Constant(x) => x.is_consty(), + Binary(x) => x.is_consty(), + Unary(x) => x.is_consty(), + Ternary(x) => x.is_consty(), + ArrayInline(x) => x.is_consty(), + ArrayInit(x) => x.is_consty(), + ArrayAccess(x) => x.is_consty(), + ArrayRangeAccess(x) => x.is_consty(), + TupleInit(x) => x.is_consty(), + TupleAccess(x) => x.is_consty(), + CircuitInit(x) => x.is_consty(), + CircuitAccess(x) => x.is_consty(), + Call(x) => x.is_consty(), + } + } +} + +impl FromAst for Arc { + fn from_ast( + scope: &Scope, + value: &leo_ast::Expression, + expected_type: Option, + ) -> Result { + use leo_ast::Expression::*; + let expression = match value { + Identifier(identifier) => Self::from_ast(scope, identifier, expected_type)?, + Value(value) => Arc::new(Constant::from_ast(scope, value, expected_type).map(Expression::Constant)?), + Binary(binary) => { + Arc::new(BinaryExpression::from_ast(scope, binary, expected_type).map(Expression::Binary)?) + } + Unary(unary) => Arc::new(UnaryExpression::from_ast(scope, unary, expected_type).map(Expression::Unary)?), + Ternary(conditional) => { + Arc::new(TernaryExpression::from_ast(scope, conditional, expected_type).map(Expression::Ternary)?) + } + + ArrayInline(array_inline) => Arc::new( + ArrayInlineExpression::from_ast(scope, array_inline, expected_type).map(Expression::ArrayInline)?, + ), + ArrayInit(array_init) => { + Arc::new(ArrayInitExpression::from_ast(scope, array_init, expected_type).map(Expression::ArrayInit)?) + } + ArrayAccess(array_access) => Arc::new( + ArrayAccessExpression::from_ast(scope, array_access, expected_type).map(Expression::ArrayAccess)?, + ), + ArrayRangeAccess(array_range_access) => Arc::new( + ArrayRangeAccessExpression::from_ast(scope, array_range_access, expected_type) + .map(Expression::ArrayRangeAccess)?, + ), + + TupleInit(tuple_init) => { + Arc::new(TupleInitExpression::from_ast(scope, tuple_init, expected_type).map(Expression::TupleInit)?) + } + TupleAccess(tuple_access) => Arc::new( + TupleAccessExpression::from_ast(scope, tuple_access, expected_type).map(Expression::TupleAccess)?, + ), + + CircuitInit(circuit_init) => Arc::new( + CircuitInitExpression::from_ast(scope, circuit_init, expected_type).map(Expression::CircuitInit)?, + ), + CircuitMemberAccess(circuit_member) => Arc::new( + CircuitAccessExpression::from_ast(scope, circuit_member, expected_type) + .map(Expression::CircuitAccess)?, + ), + CircuitStaticFunctionAccess(circuit_member) => Arc::new( + CircuitAccessExpression::from_ast(scope, circuit_member, expected_type) + .map(Expression::CircuitAccess)?, + ), + + Call(call) => Arc::new(CallExpression::from_ast(scope, call, expected_type).map(Expression::Call)?), + }; + expression.enforce_parents(&expression); + Ok(expression) + } +} + +impl Into for &Expression { + fn into(self) -> leo_ast::Expression { + use Expression::*; + match self { + VariableRef(x) => leo_ast::Expression::Identifier(x.into()), + Constant(x) => leo_ast::Expression::Value(x.into()), + Binary(x) => leo_ast::Expression::Binary(x.into()), + Unary(x) => leo_ast::Expression::Unary(x.into()), + Ternary(x) => leo_ast::Expression::Ternary(x.into()), + ArrayInline(x) => leo_ast::Expression::ArrayInline(x.into()), + ArrayInit(x) => leo_ast::Expression::ArrayInit(x.into()), + ArrayAccess(x) => leo_ast::Expression::ArrayAccess(x.into()), + ArrayRangeAccess(x) => leo_ast::Expression::ArrayRangeAccess(x.into()), + TupleInit(x) => leo_ast::Expression::TupleInit(x.into()), + TupleAccess(x) => leo_ast::Expression::TupleAccess(x.into()), + CircuitInit(x) => leo_ast::Expression::CircuitInit(x.into()), + CircuitAccess(x) => x.into(), + Call(x) => leo_ast::Expression::Call(x.into()), + } + } +} diff --git a/asg/src/expression/ternary.rs b/asg/src/expression/ternary.rs new file mode 100644 index 0000000000..b12d70eab7 --- /dev/null +++ b/asg/src/expression/ternary.rs @@ -0,0 +1,103 @@ +// 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 . + +use crate::{AsgConvertError, ConstValue, Expression, ExpressionNode, FromAst, Node, PartialType, Scope, Span, Type}; + +use std::{ + cell::RefCell, + sync::{Arc, Weak}, +}; + +pub struct TernaryExpression { + pub parent: RefCell>>, + pub span: Option, + pub condition: Arc, + pub if_true: Arc, + pub if_false: Arc, +} + +impl Node for TernaryExpression { + fn span(&self) -> Option<&Span> { + self.span.as_ref() + } +} + +impl ExpressionNode for TernaryExpression { + fn set_parent(&self, parent: Weak) { + self.parent.replace(Some(parent)); + } + + fn get_parent(&self) -> Option> { + self.parent.borrow().as_ref().map(Weak::upgrade).flatten() + } + + fn enforce_parents(&self, expr: &Arc) { + self.condition.set_parent(Arc::downgrade(expr)); + self.if_true.set_parent(Arc::downgrade(expr)); + self.if_false.set_parent(Arc::downgrade(expr)); + } + + fn get_type(&self) -> Option { + self.if_true.get_type() + } + + fn is_mut_ref(&self) -> bool { + self.if_true.is_mut_ref() && self.if_false.is_mut_ref() + } + + fn const_value(&self) -> Option { + if let Some(ConstValue::Boolean(switch)) = self.condition.const_value() { + if switch { + self.if_true.const_value() + } else { + self.if_false.const_value() + } + } else { + None + } + } + + fn is_consty(&self) -> bool { + self.condition.is_consty() && self.if_true.is_consty() && self.if_false.is_consty() + } +} + +impl FromAst for TernaryExpression { + fn from_ast( + scope: &Scope, + value: &leo_ast::TernaryExpression, + expected_type: Option, + ) -> Result { + Ok(TernaryExpression { + parent: RefCell::new(None), + span: Some(value.span.clone()), + condition: Arc::::from_ast(scope, &*value.condition, Some(Type::Boolean.partial()))?, + if_true: Arc::::from_ast(scope, &*value.if_true, expected_type.clone())?, + if_false: Arc::::from_ast(scope, &*value.if_false, expected_type)?, + }) + } +} + +impl Into for &TernaryExpression { + fn into(self) -> leo_ast::TernaryExpression { + leo_ast::TernaryExpression { + condition: Box::new(self.condition.as_ref().into()), + if_true: Box::new(self.if_true.as_ref().into()), + if_false: Box::new(self.if_false.as_ref().into()), + span: self.span.clone().unwrap_or_default(), + } + } +} diff --git a/asg/src/expression/tuple_access.rs b/asg/src/expression/tuple_access.rs new file mode 100644 index 0000000000..3176f9c845 --- /dev/null +++ b/asg/src/expression/tuple_access.rs @@ -0,0 +1,119 @@ +// 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 . + +use crate::{AsgConvertError, ConstValue, Expression, ExpressionNode, FromAst, Node, PartialType, Scope, Span, Type}; + +use std::{ + cell::RefCell, + sync::{Arc, Weak}, +}; + +pub struct TupleAccessExpression { + pub parent: RefCell>>, + pub span: Option, + pub tuple_ref: Arc, + pub index: usize, +} + +impl Node for TupleAccessExpression { + fn span(&self) -> Option<&Span> { + self.span.as_ref() + } +} + +impl ExpressionNode for TupleAccessExpression { + fn set_parent(&self, parent: Weak) { + self.parent.replace(Some(parent)); + } + + fn get_parent(&self) -> Option> { + self.parent.borrow().as_ref().map(Weak::upgrade).flatten() + } + + fn enforce_parents(&self, expr: &Arc) { + self.tuple_ref.set_parent(Arc::downgrade(expr)); + } + + fn get_type(&self) -> Option { + match self.tuple_ref.get_type()? { + Type::Tuple(subtypes) => subtypes.get(self.index).cloned(), + _ => None, + } + } + + fn is_mut_ref(&self) -> bool { + self.tuple_ref.is_mut_ref() + } + + fn const_value(&self) -> Option { + let tuple_const = self.tuple_ref.const_value()?; + match tuple_const { + ConstValue::Tuple(sub_consts) => sub_consts.get(self.index).cloned(), + _ => None, + } + } + + fn is_consty(&self) -> bool { + self.tuple_ref.is_consty() + } +} + +impl FromAst for TupleAccessExpression { + fn from_ast( + scope: &Scope, + value: &leo_ast::TupleAccessExpression, + expected_type: Option, + ) -> Result { + let index = value + .index + .value + .parse::() + .map_err(|_| AsgConvertError::parse_index_error())?; + + let mut expected_tuple = vec![None; index + 1]; + expected_tuple[index] = expected_type; + + let tuple = Arc::::from_ast(scope, &*value.tuple, Some(PartialType::Tuple(expected_tuple)))?; + let tuple_type = tuple.get_type(); + if let Some(Type::Tuple(_items)) = tuple_type { + } else { + return Err(AsgConvertError::unexpected_type( + "a tuple", + tuple_type.map(|x| x.to_string()).as_deref(), + &value.span, + )); + } + + Ok(TupleAccessExpression { + parent: RefCell::new(None), + span: Some(value.span.clone()), + tuple_ref: tuple, + index, + }) + } +} + +impl Into for &TupleAccessExpression { + fn into(self) -> leo_ast::TupleAccessExpression { + leo_ast::TupleAccessExpression { + tuple: Box::new(self.tuple_ref.as_ref().into()), + index: leo_ast::PositiveNumber { + value: self.index.to_string(), + }, + span: self.span.clone().unwrap_or_default(), + } + } +} diff --git a/asg/src/expression/tuple_init.rs b/asg/src/expression/tuple_init.rs new file mode 100644 index 0000000000..5d7bd71cd9 --- /dev/null +++ b/asg/src/expression/tuple_init.rs @@ -0,0 +1,136 @@ +// 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 . + +use crate::{AsgConvertError, ConstValue, Expression, ExpressionNode, FromAst, Node, PartialType, Scope, Span, Type}; + +use std::{ + cell::RefCell, + sync::{Arc, Weak}, +}; + +pub struct TupleInitExpression { + pub parent: RefCell>>, + pub span: Option, + pub elements: Vec>, +} + +impl Node for TupleInitExpression { + fn span(&self) -> Option<&Span> { + self.span.as_ref() + } +} + +impl ExpressionNode for TupleInitExpression { + fn set_parent(&self, parent: Weak) { + self.parent.replace(Some(parent)); + } + + fn get_parent(&self) -> Option> { + self.parent.borrow().as_ref().map(Weak::upgrade).flatten() + } + + fn enforce_parents(&self, expr: &Arc) { + self.elements.iter().for_each(|element| { + element.set_parent(Arc::downgrade(expr)); + }) + } + + fn get_type(&self) -> Option { + let mut output = vec![]; + for element in self.elements.iter() { + output.push(element.get_type()?); + } + Some(Type::Tuple(output)) + } + + fn is_mut_ref(&self) -> bool { + false + } + + fn const_value(&self) -> Option { + let mut consts = vec![]; + for element in self.elements.iter() { + if let Some(const_value) = element.const_value() { + consts.push(const_value); + } else { + return None; + } + } + Some(ConstValue::Tuple(consts)) + } + + fn is_consty(&self) -> bool { + self.elements.iter().all(|x| x.is_consty()) + } +} + +impl FromAst for TupleInitExpression { + fn from_ast( + scope: &Scope, + value: &leo_ast::TupleInitExpression, + expected_type: Option, + ) -> Result { + let tuple_types = match expected_type { + Some(PartialType::Tuple(sub_types)) => Some(sub_types), + None => None, + x => { + return Err(AsgConvertError::unexpected_type( + "tuple", + x.map(|x| x.to_string()).as_deref(), + &value.span, + )); + } + }; + + if let Some(tuple_types) = tuple_types.as_ref() { + if tuple_types.len() != value.elements.len() { + return Err(AsgConvertError::unexpected_type( + &*format!("tuple of length {}", tuple_types.len()), + Some(&*format!("tuple of length {}", value.elements.len())), + &value.span, + )); + } + } + + let elements = value + .elements + .iter() + .enumerate() + .map(|(i, e)| { + Arc::::from_ast( + scope, + e, + tuple_types.as_ref().map(|x| x.get(i)).flatten().cloned().flatten(), + ) + }) + .collect::, AsgConvertError>>()?; + + Ok(TupleInitExpression { + parent: RefCell::new(None), + span: Some(value.span.clone()), + elements, + }) + } +} + +impl Into for &TupleInitExpression { + fn into(self) -> leo_ast::TupleInitExpression { + leo_ast::TupleInitExpression { + elements: self.elements.iter().map(|e| e.as_ref().into()).collect(), + span: self.span.clone().unwrap_or_default(), + } + } +} diff --git a/asg/src/expression/unary.rs b/asg/src/expression/unary.rs new file mode 100644 index 0000000000..0871e7d488 --- /dev/null +++ b/asg/src/expression/unary.rs @@ -0,0 +1,133 @@ +// 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 . + +use crate::{AsgConvertError, ConstValue, Expression, ExpressionNode, FromAst, Node, PartialType, Scope, Span, Type}; +pub use leo_ast::UnaryOperation; + +use std::{ + cell::RefCell, + sync::{Arc, Weak}, +}; + +pub struct UnaryExpression { + pub parent: RefCell>>, + pub span: Option, + pub operation: UnaryOperation, + pub inner: Arc, +} + +impl Node for UnaryExpression { + fn span(&self) -> Option<&Span> { + self.span.as_ref() + } +} + +impl ExpressionNode for UnaryExpression { + fn set_parent(&self, parent: Weak) { + self.parent.replace(Some(parent)); + } + + fn get_parent(&self) -> Option> { + self.parent.borrow().as_ref().map(Weak::upgrade).flatten() + } + + fn enforce_parents(&self, expr: &Arc) { + self.inner.set_parent(Arc::downgrade(expr)); + } + + fn get_type(&self) -> Option { + self.inner.get_type() + } + + fn is_mut_ref(&self) -> bool { + false + } + + fn const_value(&self) -> Option { + if let Some(inner) = self.inner.const_value() { + match self.operation { + UnaryOperation::Not => match inner { + ConstValue::Boolean(value) => Some(ConstValue::Boolean(!value)), + _ => None, + }, + UnaryOperation::Negate => { + match inner { + ConstValue::Int(value) => Some(ConstValue::Int(value.value_negate()?)), + // ConstValue::Group(value) => Some(ConstValue::Group(value)), TODO: groups + // ConstValue::Field(value) => Some(ConstValue::Field(-value)), + _ => None, + } + } + } + } else { + None + } + } + + fn is_consty(&self) -> bool { + self.inner.is_consty() + } +} + +impl FromAst for UnaryExpression { + fn from_ast( + scope: &Scope, + value: &leo_ast::UnaryExpression, + expected_type: Option, + ) -> Result { + let expected_type = match value.op { + UnaryOperation::Not => match expected_type.map(|x| x.full()).flatten() { + Some(Type::Boolean) | None => Some(Type::Boolean), + Some(type_) => { + return Err(AsgConvertError::unexpected_type( + &type_.to_string(), + Some(&*Type::Boolean.to_string()), + &value.span, + )); + } + }, + UnaryOperation::Negate => match expected_type.map(|x| x.full()).flatten() { + Some(type_ @ Type::Integer(_)) => Some(type_), + Some(Type::Group) => Some(Type::Group), + Some(Type::Field) => Some(Type::Field), + None => None, + Some(type_) => { + return Err(AsgConvertError::unexpected_type( + &type_.to_string(), + Some("integer, group, field"), + &value.span, + )); + } + }, + }; + Ok(UnaryExpression { + parent: RefCell::new(None), + span: Some(value.span.clone()), + operation: value.op.clone(), + inner: Arc::::from_ast(scope, &*value.inner, expected_type.map(Into::into))?, + }) + } +} + +impl Into for &UnaryExpression { + fn into(self) -> leo_ast::UnaryExpression { + leo_ast::UnaryExpression { + op: self.operation.clone(), + inner: Box::new(self.inner.as_ref().into()), + span: self.span.clone().unwrap_or_default(), + } + } +} diff --git a/asg/src/expression/variable_ref.rs b/asg/src/expression/variable_ref.rs new file mode 100644 index 0000000000..648a725fc0 --- /dev/null +++ b/asg/src/expression/variable_ref.rs @@ -0,0 +1,210 @@ +// 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 . + +use crate::{ + AsgConvertError, + ConstValue, + Constant, + DefinitionStatement, + Expression, + ExpressionNode, + FromAst, + Node, + PartialType, + Scope, + Span, + Statement, + Type, + Variable, + VariableDeclaration, +}; + +use std::{ + cell::RefCell, + sync::{Arc, Weak}, +}; + +pub struct VariableRef { + pub parent: RefCell>>, + pub span: Option, + pub variable: Variable, +} + +impl Node for VariableRef { + fn span(&self) -> Option<&Span> { + self.span.as_ref() + } +} + +impl ExpressionNode for VariableRef { + fn set_parent(&self, parent: Weak) { + self.parent.replace(Some(parent)); + } + + fn get_parent(&self) -> Option> { + self.parent.borrow().as_ref().map(Weak::upgrade).flatten() + } + + fn enforce_parents(&self, _expr: &Arc) {} + + fn get_type(&self) -> Option { + Some(self.variable.borrow().type_.clone()) + } + + fn is_mut_ref(&self) -> bool { + self.variable.borrow().mutable + } + + // todo: we can use use hacky ssa here to catch more cases, or just enforce ssa before asg generation finished + fn const_value(&self) -> Option { + let variable = self.variable.borrow(); + if variable.mutable || variable.assignments.len() != 1 { + return None; + } + let assignment = variable + .assignments + .get(0) + .unwrap() + .upgrade() + .expect("stale assignment for variable"); + match &*assignment { + Statement::Definition(DefinitionStatement { variables, value, .. }) => { + if variables.len() == 1 { + let defined_variable = variables.get(0).unwrap().borrow(); + assert_eq!(variable.id, defined_variable.id); + + value.const_value() + } else { + for defined_variable in variables.iter() { + let defined_variable = defined_variable.borrow(); + if defined_variable.id == variable.id { + return value.const_value(); + } + } + panic!("no corresponding tuple variable found during const destructuring (corrupt asg?)"); + } + } + _ => None, //todo unroll loops during asg phase + } + } + + fn is_consty(&self) -> bool { + let variable = self.variable.borrow(); + if variable.declaration == VariableDeclaration::IterationDefinition { + return true; + } + if variable.mutable || variable.assignments.len() != 1 { + return false; + } + let assignment = variable + .assignments + .get(0) + .unwrap() + .upgrade() + .expect("stale assignment for variable"); + + match &*assignment { + Statement::Definition(DefinitionStatement { variables, value, .. }) => { + if variables.len() == 1 { + let defined_variable = variables.get(0).unwrap().borrow(); + assert_eq!(variable.id, defined_variable.id); + + value.is_consty() + } else { + for defined_variable in variables.iter() { + let defined_variable = defined_variable.borrow(); + if defined_variable.id == variable.id { + return value.is_consty(); + } + } + panic!("no corresponding tuple variable found during const destructuring (corrupt asg?)"); + } + } + Statement::Iteration(_) => true, + _ => false, + } + } +} + +impl FromAst for Arc { + fn from_ast( + scope: &Scope, + value: &leo_ast::Identifier, + expected_type: Option, + ) -> Result, AsgConvertError> { + let variable = if value.name == "input" { + if let Some(function) = scope.borrow().resolve_current_function() { + if !function.has_input { + return Err(AsgConvertError::unresolved_reference(&value.name, &value.span)); + } + } else { + return Err(AsgConvertError::unresolved_reference(&value.name, &value.span)); + } + if let Some(input) = scope.borrow().resolve_input() { + input.container + } else { + return Err(AsgConvertError::InternalError( + "attempted to reference input when none is in scope".to_string(), + )); + } + } else { + match scope.borrow().resolve_variable(&value.name) { + Some(v) => v, + None => { + if value.name.starts_with("aleo1") { + return Ok(Arc::new(Expression::Constant(Constant { + parent: RefCell::new(None), + span: Some(value.span.clone()), + value: ConstValue::Address(value.name.clone()), + }))); + } + return Err(AsgConvertError::unresolved_reference(&value.name, &value.span)); + } + } + }; + + let variable_ref = VariableRef { + parent: RefCell::new(None), + span: Some(value.span.clone()), + variable: variable.clone(), + }; + let expression = Arc::new(Expression::VariableRef(variable_ref)); + + if let Some(expected_type) = expected_type { + let type_ = expression + .get_type() + .ok_or_else(|| AsgConvertError::unresolved_reference(&value.name, &value.span))?; + if !expected_type.matches(&type_) { + return Err(AsgConvertError::unexpected_type( + &expected_type.to_string(), + Some(&*type_.to_string()), + &value.span, + )); + } + } + + let mut variable_ref = variable.borrow_mut(); + variable_ref.references.push(Arc::downgrade(&expression)); + + Ok(expression) + } +} + +impl Into for &VariableRef { + fn into(self) -> leo_ast::Identifier { + self.variable.borrow().name.clone() + } +} diff --git a/asg/src/import.rs b/asg/src/import.rs new file mode 100644 index 0000000000..8924530b0f --- /dev/null +++ b/asg/src/import.rs @@ -0,0 +1,71 @@ +// 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 . + +//! Helper methods for resolving imported packages. + +use crate::{AsgConvertError, Program, Span}; + +use indexmap::IndexMap; + +pub trait ImportResolver { + fn resolve_package(&mut self, package_segments: &[&str], span: &Span) -> Result, AsgConvertError>; +} + +pub struct NullImportResolver; + +impl ImportResolver for NullImportResolver { + fn resolve_package( + &mut self, + _package_segments: &[&str], + _span: &Span, + ) -> Result, AsgConvertError> { + Ok(None) + } +} + +pub struct CoreImportResolver<'a, T: ImportResolver + 'static>(pub &'a mut T); + +impl<'a, T: ImportResolver + 'static> ImportResolver for CoreImportResolver<'a, T> { + fn resolve_package(&mut self, package_segments: &[&str], span: &Span) -> Result, AsgConvertError> { + if !package_segments.is_empty() && package_segments.get(0).unwrap() == &"core" { + Ok(crate::resolve_core_module(&*package_segments[1..].join("."))?) + } else { + self.0.resolve_package(package_segments, span) + } + } +} + +pub struct StandardImportResolver; + +impl ImportResolver for StandardImportResolver { + fn resolve_package( + &mut self, + _package_segments: &[&str], + _span: &Span, + ) -> Result, AsgConvertError> { + Ok(None) + } +} + +pub struct MockedImportResolver { + pub packages: IndexMap, +} + +impl ImportResolver for MockedImportResolver { + fn resolve_package(&mut self, package_segments: &[&str], _span: &Span) -> Result, AsgConvertError> { + Ok(self.packages.get(&package_segments.join(".")).cloned()) + } +} diff --git a/asg/src/input.rs b/asg/src/input.rs new file mode 100644 index 0000000000..18023bd6fd --- /dev/null +++ b/asg/src/input.rs @@ -0,0 +1,147 @@ +// 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 . + +use crate::{Circuit, CircuitBody, CircuitMember, CircuitMemberBody, Identifier, Scope, Type, Variable, WeakType}; + +use indexmap::IndexMap; +use std::{ + cell::RefCell, + sync::{Arc, Weak}, +}; + +/// Stores program input values as asg nodes. +#[derive(Clone)] +pub struct Input { + pub registers: Arc, + pub state: Arc, + pub state_leaf: Arc, + pub record: Arc, + pub container_circuit: Arc, + pub container: Variable, +} + +pub const CONTAINER_PSEUDO_CIRCUIT: &str = "$InputContainer"; +pub const REGISTERS_PSEUDO_CIRCUIT: &str = "$InputRegister"; +pub const RECORD_PSEUDO_CIRCUIT: &str = "$InputRecord"; +pub const STATE_PSEUDO_CIRCUIT: &str = "$InputState"; +pub const STATE_LEAF_PSEUDO_CIRCUIT: &str = "$InputStateLeaf"; + +impl Input { + fn make_header(name: &str) -> Arc { + Arc::new(Circuit { + id: uuid::Uuid::new_v4(), + name: RefCell::new(Identifier::new(name.to_string())), + body: RefCell::new(Weak::new()), + members: RefCell::new(IndexMap::new()), + core_mapping: RefCell::new(None), + }) + } + + fn make_body(scope: &Scope, circuit: &Arc) -> Arc { + let body = Arc::new(CircuitBody { + scope: scope.clone(), + span: None, + circuit: circuit.clone(), + members: RefCell::new(IndexMap::new()), + }); + circuit.body.replace(Arc::downgrade(&body)); + body + } + + pub fn new(scope: &Scope) -> Self { + let registers = Self::make_header(REGISTERS_PSEUDO_CIRCUIT); + let record = Self::make_header(RECORD_PSEUDO_CIRCUIT); + let state = Self::make_header(STATE_PSEUDO_CIRCUIT); + let state_leaf = Self::make_header(STATE_LEAF_PSEUDO_CIRCUIT); + + let mut container_members = IndexMap::new(); + container_members.insert( + "registers".to_string(), + CircuitMember::Variable(WeakType::Circuit(Arc::downgrade(®isters))), + ); + container_members.insert( + "record".to_string(), + CircuitMember::Variable(WeakType::Circuit(Arc::downgrade(&record))), + ); + container_members.insert( + "state".to_string(), + CircuitMember::Variable(WeakType::Circuit(Arc::downgrade(&state))), + ); + container_members.insert( + "state_leaf".to_string(), + CircuitMember::Variable(WeakType::Circuit(Arc::downgrade(&state_leaf))), + ); + + let container_circuit = Arc::new(Circuit { + id: uuid::Uuid::new_v4(), + name: RefCell::new(Identifier::new(CONTAINER_PSEUDO_CIRCUIT.to_string())), + body: RefCell::new(Weak::new()), + members: RefCell::new(container_members), + core_mapping: RefCell::new(None), + }); + + let registers_body = Self::make_body(scope, ®isters); + let record_body = Self::make_body(scope, &record); + let state_body = Self::make_body(scope, &state); + let state_leaf_body = Self::make_body(scope, &state_leaf); + + let mut container_body_members = IndexMap::new(); + container_body_members.insert( + "registers".to_string(), + CircuitMemberBody::Variable(Type::Circuit(registers)), + ); + container_body_members.insert("record".to_string(), CircuitMemberBody::Variable(Type::Circuit(record))); + container_body_members.insert("state".to_string(), CircuitMemberBody::Variable(Type::Circuit(state))); + container_body_members.insert( + "state_leaf".to_string(), + CircuitMemberBody::Variable(Type::Circuit(state_leaf)), + ); + + let container_circuit_body = Arc::new(CircuitBody { + scope: scope.clone(), + span: None, + circuit: container_circuit.clone(), + members: RefCell::new(container_body_members), + }); + container_circuit.body.replace(Arc::downgrade(&container_circuit_body)); + + Input { + registers: registers_body, + record: record_body, + state: state_body, + state_leaf: state_leaf_body, + container_circuit: container_circuit_body, + container: Arc::new(RefCell::new(crate::InnerVariable { + id: uuid::Uuid::new_v4(), + name: Identifier::new("input".to_string()), + type_: Type::Circuit(container_circuit), + mutable: false, + declaration: crate::VariableDeclaration::Input, + references: vec![], + assignments: vec![], + })), + } + } +} + +impl Circuit { + pub fn is_input_pseudo_circuit(&self) -> bool { + matches!( + &*self.name.borrow().name, + REGISTERS_PSEUDO_CIRCUIT | RECORD_PSEUDO_CIRCUIT | STATE_PSEUDO_CIRCUIT | STATE_LEAF_PSEUDO_CIRCUIT + ) + } +} diff --git a/asg/src/lib.rs b/asg/src/lib.rs new file mode 100644 index 0000000000..8c59d1ceaa --- /dev/null +++ b/asg/src/lib.rs @@ -0,0 +1,119 @@ +// 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 . + +//! The abstract semantic graph (asg) for a Leo program. +//! +//! This module contains the [`Asg`] type, an abstract data type that represents a Leo program +//! as a series of graph nodes. The [`Asg`] type is at a greater level of abstraction than an [`Ast`]. +//! +//! A new [`Asg`] type can be created from an [`Ast`]. +//! Converting to an [`Asg`] provides greater type safety by canonicalizing and checking program types. + +#![allow(clippy::from_over_into)] +#[macro_use] +extern crate thiserror; + +pub mod checks; +pub use checks::*; + +pub mod const_value; +pub use const_value::*; + +pub mod error; +pub use error::*; + +pub mod expression; +pub use expression::*; + +pub mod import; +pub use import::*; + +mod input; +pub use input::*; + +pub mod node; +pub use node::*; + +pub mod prelude; +pub use prelude::*; + +pub mod program; +pub use program::*; + +pub mod reducer; +pub use reducer::*; + +pub mod scope; +pub use scope::*; + +pub mod statement; +pub use statement::*; + +pub mod type_; +pub use type_::*; + +pub mod variable; +pub use variable::*; + +pub use leo_ast::{Identifier, Span}; + +use std::path::Path; + +/// The abstract semantic graph (asg) for a Leo program. +/// +/// The [`Asg`] type represents a Leo program as a series of recursive data types. +/// These data types form a graph that begins from a [`Program`] type node. +/// +/// A new [`Asg`] can be created from an [`Ast`] generated in the `ast` module. +// #[derive(Debug, Eq, PartialEq)] +// pub struct Asg { +// asg: InnerProgram, +// } +// +// impl Asg { +// /// Creates a new asg from a given ast tree and import resolver. +// pub fn new( +// content: leo_ast::Program, +// resolver: &mut T, +// ) -> Result { +// InnerProgram::new(&content, resolver) +// } +// +// /// Returns a reference to the inner program ast representation. +// pub fn into_repr(self) -> Program { +// self.asg +// } +// } + +pub fn load_ast, Y: AsRef>(path: T, content: Y) -> Result { + // Parses the Leo file and constructs a grammar ast. + let ast = leo_grammar::Grammar::new(path.as_ref(), content.as_ref()) + .map_err(|e| AsgConvertError::InternalError(format!("ast: {:?}", e)))?; + + // Parses the pest ast and constructs a Leo ast. + Ok(leo_ast::Ast::new("load_ast", &ast)?.into_repr()) +} + +pub fn load_asg_from_ast( + content: leo_ast::Program, + resolver: &mut T, +) -> Result { + InnerProgram::new(&content, resolver) +} + +pub fn load_asg(content: &str, resolver: &mut T) -> Result { + InnerProgram::new(&load_ast("input.leo", content)?, resolver) +} diff --git a/asg/src/node.rs b/asg/src/node.rs new file mode 100644 index 0000000000..e121a3c9f4 --- /dev/null +++ b/asg/src/node.rs @@ -0,0 +1,28 @@ +// 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 . + +use crate::{AsgConvertError, PartialType, Scope, Span}; + +/// A node in the abstract semantic graph. +pub trait Node { + fn span(&self) -> Option<&Span>; +} + +pub(super) trait FromAst: Sized + 'static { + // expected_type contract: if present, output expression must be of type expected_type. + // type of an element may NEVER be None unless it is functionally a non-expression. (static call targets, function ref call targets are not expressions) + fn from_ast(scope: &Scope, value: &T, expected_type: Option) -> Result; +} diff --git a/asg/src/prelude.rs b/asg/src/prelude.rs new file mode 100644 index 0000000000..992fa91e30 --- /dev/null +++ b/asg/src/prelude.rs @@ -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 . + +//todo: we should merge this with core + +use crate::{AsgConvertError, Program}; + +// todo: make asg deep copy so we can cache resolved core modules +// todo: figure out how to do headers without bogus returns + +pub fn resolve_core_module(module: &str) -> Result, AsgConvertError> { + match module { + "unstable.blake2s" => { + let asg = crate::load_asg( + r#" + circuit Blake2s { + function hash(seed: [u8; 32], message: [u8; 32]) -> [u8; 32] { + return [0; 32] + } + } + "#, + &mut crate::NullImportResolver, + )?; + asg.borrow().set_core_mapping("blake2s"); + Ok(Some(asg)) + } + _ => Ok(None), + } +} diff --git a/asg/src/program/circuit.rs b/asg/src/program/circuit.rs new file mode 100644 index 0000000000..7a4368d8be --- /dev/null +++ b/asg/src/program/circuit.rs @@ -0,0 +1,199 @@ +// 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 . + +use crate::{AsgConvertError, Function, FunctionBody, Identifier, InnerScope, Node, Scope, Span, Type, WeakType}; + +use indexmap::IndexMap; +use std::{ + cell::RefCell, + sync::{Arc, Weak}, +}; +use uuid::Uuid; + +pub enum CircuitMemberBody { + Variable(Type), + Function(Arc), +} + +pub enum CircuitMember { + Variable(WeakType), + Function(Arc), +} + +pub struct Circuit { + pub id: Uuid, + pub name: RefCell, + pub core_mapping: RefCell>, + pub body: RefCell>, + pub members: RefCell>, +} + +impl PartialEq for Circuit { + fn eq(&self, other: &Circuit) -> bool { + if self.name != other.name { + return false; + } + self.id == other.id + } +} +impl Eq for Circuit {} + +pub struct CircuitBody { + pub scope: Scope, + pub span: Option, + pub circuit: Arc, + pub members: RefCell>, +} + +impl PartialEq for CircuitBody { + fn eq(&self, other: &CircuitBody) -> bool { + self.circuit == other.circuit + } +} +impl Eq for CircuitBody {} + +impl Node for CircuitMemberBody { + fn span(&self) -> Option<&Span> { + None + } +} + +impl Circuit { + pub(super) fn init(value: &leo_ast::Circuit) -> Arc { + Arc::new(Circuit { + id: Uuid::new_v4(), + name: RefCell::new(value.circuit_name.clone()), + body: RefCell::new(Weak::new()), + members: RefCell::new(IndexMap::new()), + core_mapping: RefCell::new(None), + }) + } + + pub(super) fn from_ast(self: Arc, scope: &Scope, value: &leo_ast::Circuit) -> Result<(), AsgConvertError> { + let new_scope = InnerScope::make_subscope(scope); // temporary scope for function headers + new_scope.borrow_mut().circuit_self = Some(self.clone()); + + let mut members = self.members.borrow_mut(); + for member in value.members.iter() { + match member { + leo_ast::CircuitMember::CircuitVariable(name, type_) => { + members.insert( + name.name.clone(), + CircuitMember::Variable(new_scope.borrow().resolve_ast_type(type_)?.into()), + ); + } + leo_ast::CircuitMember::CircuitFunction(function) => { + let asg_function = Arc::new(Function::from_ast(&new_scope, function)?); + + members.insert(function.identifier.name.clone(), CircuitMember::Function(asg_function)); + } + } + } + + for (_, member) in members.iter() { + if let CircuitMember::Function(func) = member { + func.circuit.borrow_mut().replace(Arc::downgrade(&self)); + } + } + + Ok(()) + } +} + +impl CircuitBody { + pub(super) fn from_ast( + scope: &Scope, + value: &leo_ast::Circuit, + circuit: Arc, + ) -> Result { + let mut members = IndexMap::new(); + let new_scope = InnerScope::make_subscope(scope); + new_scope.borrow_mut().circuit_self = Some(circuit.clone()); + + for member in value.members.iter() { + match member { + leo_ast::CircuitMember::CircuitVariable(name, type_) => { + if members.contains_key(&name.name) { + return Err(AsgConvertError::redefined_circuit_member( + &value.circuit_name.name, + &name.name, + &name.span, + )); + } + members.insert( + name.name.clone(), + CircuitMemberBody::Variable(new_scope.borrow().resolve_ast_type(type_)?), + ); + } + leo_ast::CircuitMember::CircuitFunction(function) => { + if members.contains_key(&function.identifier.name) { + return Err(AsgConvertError::redefined_circuit_member( + &value.circuit_name.name, + &function.identifier.name, + &function.identifier.span, + )); + } + let asg_function = { + let circuit_members = circuit.members.borrow(); + match circuit_members.get(&function.identifier.name).unwrap() { + CircuitMember::Function(f) => f.clone(), + _ => unimplemented!(), + } + }; + let function_body = Arc::new(FunctionBody::from_ast(&new_scope, function, asg_function.clone())?); + asg_function.body.replace(Arc::downgrade(&function_body)); + + members.insert( + function.identifier.name.clone(), + CircuitMemberBody::Function(function_body), + ); + } + } + } + + Ok(CircuitBody { + span: Some(value.circuit_name.span.clone()), + circuit, + members: RefCell::new(members), + scope: scope.clone(), + }) + } +} + +impl Into for &Circuit { + fn into(self) -> leo_ast::Circuit { + let members = match self.body.borrow().upgrade() { + Some(body) => body + .members + .borrow() + .iter() + .map(|(name, member)| match &member { + CircuitMemberBody::Variable(type_) => { + leo_ast::CircuitMember::CircuitVariable(Identifier::new(name.clone()), type_.into()) + } + CircuitMemberBody::Function(func) => { + leo_ast::CircuitMember::CircuitFunction(func.function.as_ref().into()) + } + }) + .collect(), + None => vec![], + }; + leo_ast::Circuit { + circuit_name: self.name.borrow().clone(), + members, + } + } +} diff --git a/asg/src/program/function.rs b/asg/src/program/function.rs new file mode 100644 index 0000000000..d411db5977 --- /dev/null +++ b/asg/src/program/function.rs @@ -0,0 +1,248 @@ +// 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 . + +use crate::{ + AsgConvertError, + BlockStatement, + Circuit, + FromAst, + Identifier, + InnerScope, + MonoidalDirector, + ReturnPathReducer, + Scope, + Span, + Statement, + Type, + Variable, + WeakType, +}; +use leo_ast::FunctionInput; + +use std::{ + cell::RefCell, + sync::{Arc, Weak}, +}; +use uuid::Uuid; + +#[derive(PartialEq)] +pub enum FunctionQualifier { + SelfRef, + MutSelfRef, + Static, +} + +pub struct Function { + pub id: Uuid, + pub name: RefCell, + pub output: WeakType, + pub has_input: bool, + pub argument_types: Vec, + pub circuit: RefCell>>, + pub body: RefCell>, + pub qualifier: FunctionQualifier, +} + +impl PartialEq for Function { + fn eq(&self, other: &Function) -> bool { + if self.name.borrow().name != other.name.borrow().name { + return false; + } + self.id == other.id + } +} +impl Eq for Function {} + +pub struct FunctionBody { + pub span: Option, + pub function: Arc, + pub arguments: Vec, + pub body: Arc, + pub scope: Scope, +} + +impl PartialEq for FunctionBody { + fn eq(&self, other: &FunctionBody) -> bool { + self.function == other.function + } +} +impl Eq for FunctionBody {} + +impl Function { + pub(crate) fn from_ast(scope: &Scope, value: &leo_ast::Function) -> Result { + let output: Type = value + .output + .as_ref() + .map(|t| scope.borrow().resolve_ast_type(t)) + .transpose()? + .unwrap_or_else(|| Type::Tuple(vec![])); + let mut qualifier = FunctionQualifier::Static; + let mut has_input = false; + + let mut argument_types = vec![]; + { + for input in value.input.iter() { + match input { + FunctionInput::InputKeyword(_) => { + has_input = true; + } + FunctionInput::SelfKeyword(_) => { + qualifier = FunctionQualifier::SelfRef; + } + FunctionInput::MutSelfKeyword(_) => { + qualifier = FunctionQualifier::MutSelfRef; + } + FunctionInput::Variable(leo_ast::FunctionInputVariable { type_, .. }) => { + argument_types.push(scope.borrow().resolve_ast_type(&type_)?.into()); + } + } + } + } + if qualifier != FunctionQualifier::Static && scope.borrow().circuit_self.is_none() { + return Err(AsgConvertError::invalid_self_in_global(&value.span)); + } + Ok(Function { + id: Uuid::new_v4(), + name: RefCell::new(value.identifier.clone()), + output: output.into(), + has_input, + argument_types, + circuit: RefCell::new(None), + body: RefCell::new(Weak::new()), + qualifier, + }) + } +} + +impl FunctionBody { + pub(super) fn from_ast( + scope: &Scope, + value: &leo_ast::Function, + function: Arc, + ) -> Result { + let new_scope = InnerScope::make_subscope(scope); + let mut arguments = vec![]; + { + let mut scope_borrow = new_scope.borrow_mut(); + if function.qualifier != FunctionQualifier::Static { + let circuit = function.circuit.borrow(); + let self_variable = Arc::new(RefCell::new(crate::InnerVariable { + id: Uuid::new_v4(), + name: Identifier::new("self".to_string()), + type_: Type::Circuit(circuit.as_ref().unwrap().upgrade().unwrap()), + mutable: function.qualifier == FunctionQualifier::MutSelfRef, + declaration: crate::VariableDeclaration::Parameter, + references: vec![], + assignments: vec![], + })); + scope_borrow.variables.insert("self".to_string(), self_variable); + } + scope_borrow.function = Some(function.clone()); + for input in value.input.iter() { + match input { + FunctionInput::InputKeyword(_) => {} + FunctionInput::SelfKeyword(_) => {} + FunctionInput::MutSelfKeyword(_) => {} + FunctionInput::Variable(leo_ast::FunctionInputVariable { + identifier, + mutable, + type_, + span: _span, + }) => { + let variable = Arc::new(RefCell::new(crate::InnerVariable { + id: Uuid::new_v4(), + name: identifier.clone(), + type_: scope_borrow.resolve_ast_type(&type_)?, + mutable: *mutable, + declaration: crate::VariableDeclaration::Parameter, + references: vec![], + assignments: vec![], + })); + arguments.push(variable.clone()); + scope_borrow.variables.insert(identifier.name.clone(), variable); + } + } + } + } + let main_block = BlockStatement::from_ast(&new_scope, &value.block, None)?; + let mut director = MonoidalDirector::new(ReturnPathReducer::new()); + if !director.reduce_block(&main_block).0 && !function.output.is_unit() { + return Err(AsgConvertError::function_missing_return( + &function.name.borrow().name, + &value.span, + )); + } + + #[allow(clippy::never_loop)] // TODO @Protryon: How should we return multiple errors? + for (span, error) in director.reducer().errors { + return Err(AsgConvertError::function_return_validation( + &function.name.borrow().name, + &error, + &span, + )); + } + + Ok(FunctionBody { + span: Some(value.span.clone()), + function, + arguments, + body: Arc::new(Statement::Block(main_block)), + scope: new_scope, + }) + } +} + +impl Into for &Function { + fn into(self) -> leo_ast::Function { + let (input, body, span) = match self.body.borrow().upgrade() { + Some(body) => ( + body.arguments + .iter() + .map(|variable| { + let variable = variable.borrow(); + leo_ast::FunctionInput::Variable(leo_ast::FunctionInputVariable { + identifier: variable.name.clone(), + mutable: variable.mutable, + type_: (&variable.type_).into(), + span: Span::default(), + }) + }) + .collect(), + match body.body.as_ref() { + Statement::Block(block) => block.into(), + _ => unimplemented!(), + }, + body.span.clone().unwrap_or_default(), + ), + None => ( + vec![], + leo_ast::Block { + statements: vec![], + span: Default::default(), + }, + Default::default(), + ), + }; + let output: Type = self.output.clone().into(); + leo_ast::Function { + identifier: self.name.borrow().clone(), + input, + block: body, + output: Some((&output).into()), + span, + } + } +} diff --git a/asg/src/program/mod.rs b/asg/src/program/mod.rs new file mode 100644 index 0000000000..9dffb92481 --- /dev/null +++ b/asg/src/program/mod.rs @@ -0,0 +1,453 @@ +// 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 . + +//! This module defines the program node for an asg. +//! +//! + +mod circuit; +pub use circuit::*; + +mod function; +pub use function::*; + +use crate::{AsgConvertError, ImportResolver, InnerScope, Input, Scope}; +use leo_ast::{Identifier, Package, PackageAccess, Span}; + +use indexmap::IndexMap; +use std::{cell::RefCell, sync::Arc}; +use uuid::Uuid; + +/// Stores the Leo program abstract semantic graph (asg). +#[derive(Clone)] +pub struct InnerProgram { + /// The unique id of the program. + pub id: Uuid, + + /// The program file name. + pub name: String, + + /// The packages imported by this program. + /// these should generally not be accessed directly, but through scoped imports + pub imported_modules: IndexMap, + + /// Maps test name => test code block. + pub test_functions: IndexMap, Option)>, // identifier = test input file + + /// Maps function name => function code block. + pub functions: IndexMap>, + + /// Maps circuit name => circuit code block. + pub circuits: IndexMap>, + + /// Bindings for names and additional program context. + pub scope: Scope, +} + +pub type Program = Arc>; + +/// Enumerates what names are imported from a package. +enum ImportSymbol { + /// Import the symbol by name. + Direct(String), + + /// Import the symbol by name and store it under an alias. + Alias(String, String), // from remote -> to local + + /// Import all symbols from the package. + All, +} + +fn resolve_import_package( + output: &mut Vec<(Vec, ImportSymbol, Span)>, + mut package_segments: Vec, + package: &Package, +) { + package_segments.push(package.name.name.clone()); + + resolve_import_package_access(output, package_segments, &package.access); +} + +fn resolve_import_package_access( + output: &mut Vec<(Vec, ImportSymbol, Span)>, + package_segments: Vec, + package: &PackageAccess, +) { + match package { + PackageAccess::Star(span) => { + output.push((package_segments, ImportSymbol::All, span.clone())); + } + PackageAccess::SubPackage(subpackage) => { + resolve_import_package(output, package_segments, &*subpackage); + } + PackageAccess::Symbol(symbol) => { + let span = symbol.symbol.span.clone(); + let symbol = if let Some(alias) = symbol.alias.as_ref() { + ImportSymbol::Alias(symbol.symbol.name.clone(), alias.name.clone()) + } else { + ImportSymbol::Direct(symbol.symbol.name.clone()) + }; + output.push((package_segments, symbol, span)); + } + PackageAccess::Multiple(subaccesses) => { + for subaccess in subaccesses.iter() { + resolve_import_package_access(output, package_segments.clone(), &subaccess); + } + } + } +} + +impl InnerProgram { + /// Returns a new Leo program asg from the given Leo program ast and imports. + /// + /// stages: + /// 1. resolve imports into super scope + /// 2. finalize declared types + /// 3. finalize declared functions + /// 4. resolve all asg nodes + /// + pub fn new( + value: &leo_ast::Program, + import_resolver: &mut T, + ) -> Result { + // Recursively extract imported symbols. + let mut imported_symbols: Vec<(Vec, ImportSymbol, Span)> = vec![]; + for import in value.imports.iter() { + resolve_import_package(&mut imported_symbols, vec![], &import.package); + } + + // Create package list. + let mut deduplicated_imports: IndexMap, Span> = IndexMap::new(); + for (package, _symbol, span) in imported_symbols.iter() { + deduplicated_imports.insert(package.clone(), span.clone()); + } + + let mut wrapped_resolver = crate::CoreImportResolver(import_resolver); + + // Load imported programs. + let mut resolved_packages: IndexMap, Program> = IndexMap::new(); + for (package, span) in deduplicated_imports.iter() { + let pretty_package = package.join("."); + + let resolved_package = + match wrapped_resolver.resolve_package(&package.iter().map(|x| &**x).collect::>()[..], span)? { + Some(x) => x, + None => return Err(AsgConvertError::unresolved_import(&*pretty_package, &Span::default())), + }; + + resolved_packages.insert(package.clone(), resolved_package); + } + + let mut imported_functions: IndexMap> = IndexMap::new(); + let mut imported_circuits: IndexMap> = IndexMap::new(); + + // Prepare locally relevant scope of imports. + for (package, symbol, span) in imported_symbols.into_iter() { + let pretty_package = package.join("."); + + let resolved_package = resolved_packages + .get(&package) + .expect("could not find preloaded package"); + let resolved_package = resolved_package.borrow(); + match symbol { + ImportSymbol::All => { + imported_functions.extend(resolved_package.functions.clone().into_iter()); + imported_circuits.extend(resolved_package.circuits.clone().into_iter()); + } + ImportSymbol::Direct(name) => { + if let Some(function) = resolved_package.functions.get(&name) { + imported_functions.insert(name.clone(), function.clone()); + } else if let Some(function) = resolved_package.circuits.get(&name) { + imported_circuits.insert(name.clone(), function.clone()); + } else { + return Err(AsgConvertError::unresolved_import( + &*format!("{}.{}", pretty_package, name), + &span, + )); + } + } + ImportSymbol::Alias(name, alias) => { + if let Some(function) = resolved_package.functions.get(&name) { + imported_functions.insert(alias.clone(), function.clone()); + } else if let Some(function) = resolved_package.circuits.get(&name) { + imported_circuits.insert(alias.clone(), function.clone()); + } else { + return Err(AsgConvertError::unresolved_import( + &*format!("{}.{}", pretty_package, name), + &span, + )); + } + } + } + } + + let import_scope = Arc::new(RefCell::new(InnerScope { + id: uuid::Uuid::new_v4(), + parent_scope: None, + circuit_self: None, + variables: IndexMap::new(), + functions: imported_functions + .iter() + .map(|(name, func)| (name.clone(), func.function.clone())) + .collect(), + circuits: imported_circuits + .iter() + .map(|(name, circuit)| (name.clone(), circuit.circuit.clone())) + .collect(), + function: None, + input: None, + })); + + // Prepare header-like scope entries. + let mut proto_circuits = IndexMap::new(); + for (name, circuit) in value.circuits.iter() { + assert_eq!(name.name, circuit.circuit_name.name); + let asg_circuit = Circuit::init(circuit); + + proto_circuits.insert(name.name.clone(), asg_circuit); + } + + let scope = Arc::new(RefCell::new(InnerScope { + input: Some(Input::new(&import_scope)), // we use import_scope to avoid recursive scope ref here + id: uuid::Uuid::new_v4(), + parent_scope: Some(import_scope), + circuit_self: None, + variables: IndexMap::new(), + functions: IndexMap::new(), + circuits: proto_circuits + .iter() + .map(|(name, circuit)| (name.clone(), circuit.clone())) + .collect(), + function: None, + })); + + for (name, circuit) in value.circuits.iter() { + assert_eq!(name.name, circuit.circuit_name.name); + let asg_circuit = proto_circuits.get(&name.name).unwrap(); + + asg_circuit.clone().from_ast(&scope, &circuit)?; + } + + let mut proto_test_functions = IndexMap::new(); + for (name, test_function) in value.tests.iter() { + assert_eq!(name.name, test_function.function.identifier.name); + let function = Arc::new(Function::from_ast(&scope, &test_function.function)?); + + proto_test_functions.insert(name.name.clone(), function); + } + + let mut proto_functions = IndexMap::new(); + for (name, function) in value.functions.iter() { + assert_eq!(name.name, function.identifier.name); + let asg_function = Arc::new(Function::from_ast(&scope, function)?); + + scope + .borrow_mut() + .functions + .insert(name.name.clone(), asg_function.clone()); + proto_functions.insert(name.name.clone(), asg_function); + } + + // Load concrete definitions. + let mut test_functions = IndexMap::new(); + for (name, test_function) in value.tests.iter() { + assert_eq!(name.name, test_function.function.identifier.name); + let function = proto_test_functions.get(&name.name).unwrap(); + + let body = Arc::new(FunctionBody::from_ast( + &scope, + &test_function.function, + function.clone(), + )?); + function.body.replace(Arc::downgrade(&body)); + + test_functions.insert(name.name.clone(), (body, test_function.input_file.clone())); + } + + let mut functions = IndexMap::new(); + for (name, function) in value.functions.iter() { + assert_eq!(name.name, function.identifier.name); + let asg_function = proto_functions.get(&name.name).unwrap(); + + let body = Arc::new(FunctionBody::from_ast(&scope, function, asg_function.clone())?); + asg_function.body.replace(Arc::downgrade(&body)); + + functions.insert(name.name.clone(), body); + } + + let mut circuits = IndexMap::new(); + for (name, circuit) in value.circuits.iter() { + assert_eq!(name.name, circuit.circuit_name.name); + let asg_circuit = proto_circuits.get(&name.name).unwrap(); + let body = Arc::new(CircuitBody::from_ast(&scope, circuit, asg_circuit.clone())?); + asg_circuit.body.replace(Arc::downgrade(&body)); + + circuits.insert(name.name.clone(), body); + } + + Ok(Arc::new(RefCell::new(InnerProgram { + id: Uuid::new_v4(), + name: value.name.clone(), + test_functions, + functions, + circuits, + imported_modules: resolved_packages + .into_iter() + .map(|(package, program)| (package.join("."), program)) + .collect(), + scope, + }))) + } + + pub(crate) fn set_core_mapping(&self, mapping: &str) { + for (_, circuit) in self.circuits.iter() { + circuit.circuit.core_mapping.replace(Some(mapping.to_string())); + } + } +} + +struct InternalIdentifierGenerator { + next: usize, +} + +impl Iterator for InternalIdentifierGenerator { + type Item = String; + + fn next(&mut self) -> Option { + let out = format!("$_{}_", self.next); + self.next += 1; + Some(out) + } +} +/// Returns an ast from the given asg program. +pub fn reform_ast(program: &Program) -> leo_ast::Program { + let mut all_programs: IndexMap = IndexMap::new(); + let mut program_stack = program.borrow().imported_modules.clone(); + while let Some((module, program)) = program_stack.pop() { + if all_programs.contains_key(&module) { + continue; + } + all_programs.insert(module, program.clone()); + program_stack.extend(program.borrow().imported_modules.clone()); + } + all_programs.insert("".to_string(), program.clone()); + let core_programs: Vec<_> = all_programs + .iter() + .filter(|(module, _)| module.starts_with("core.")) + .map(|(module, program)| (module.clone(), program.clone())) + .collect(); + all_programs.retain(|module, _| !module.starts_with("core.")); + + let mut all_circuits: IndexMap> = IndexMap::new(); + let mut all_functions: IndexMap> = IndexMap::new(); + let mut all_test_functions: IndexMap, Option)> = IndexMap::new(); + let mut identifiers = InternalIdentifierGenerator { next: 0 }; + for (_, program) in all_programs.into_iter() { + let program = program.borrow(); + for (name, circuit) in program.circuits.iter() { + let identifier = format!("{}{}", identifiers.next().unwrap(), name); + circuit.circuit.name.borrow_mut().name = identifier.clone(); + all_circuits.insert(identifier, circuit.clone()); + } + for (name, function) in program.functions.iter() { + let identifier = if name == "main" { + "main".to_string() + } else { + format!("{}{}", identifiers.next().unwrap(), name) + }; + function.function.name.borrow_mut().name = identifier.clone(); + all_functions.insert(identifier, function.clone()); + } + for (name, function) in program.test_functions.iter() { + let identifier = format!("{}{}", identifiers.next().unwrap(), name); + function.0.function.name.borrow_mut().name = identifier.clone(); + all_test_functions.insert(identifier, function.clone()); + } + } + + leo_ast::Program { + name: "ast_aggregate".to_string(), + imports: core_programs + .iter() + .map(|(module, _)| leo_ast::ImportStatement { + package: leo_ast::Package { + name: Identifier::new(module.clone()), + access: leo_ast::PackageAccess::Star(Span::default()), + span: Default::default(), + }, + span: Span::default(), + }) + .collect(), + expected_input: vec![], + tests: all_test_functions + .into_iter() + .map(|(_, (function, ident))| { + (function.function.name.borrow().clone(), leo_ast::TestFunction { + function: function.function.as_ref().into(), + input_file: ident, + }) + }) + .collect(), + functions: all_functions + .into_iter() + .map(|(_, function)| { + ( + function.function.name.borrow().clone(), + function.function.as_ref().into(), + ) + }) + .collect(), + circuits: all_circuits + .into_iter() + .map(|(_, circuit)| (circuit.circuit.name.borrow().clone(), circuit.circuit.as_ref().into())) + .collect(), + } +} + +impl Into for &InnerProgram { + fn into(self) -> leo_ast::Program { + leo_ast::Program { + name: self.name.clone(), + imports: vec![], + expected_input: vec![], + circuits: self + .circuits + .iter() + .map(|(_, circuit)| (circuit.circuit.name.borrow().clone(), circuit.circuit.as_ref().into())) + .collect(), + functions: self + .functions + .iter() + .map(|(_, function)| { + ( + function.function.name.borrow().clone(), + function.function.as_ref().into(), + ) + }) + .collect(), + tests: self + .test_functions + .iter() + .map(|(_, function)| { + (function.0.function.name.borrow().clone(), leo_ast::TestFunction { + function: function.0.function.as_ref().into(), + input_file: function.1.clone(), + }) + }) + .collect(), + } + } +} diff --git a/asg/src/reducer/mod.rs b/asg/src/reducer/mod.rs new file mode 100644 index 0000000000..95f82553eb --- /dev/null +++ b/asg/src/reducer/mod.rs @@ -0,0 +1,27 @@ +// 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 . + +//! This module contains the reducer which iterates through ast nodes - converting them into +//! asg nodes and saving relevant information. + +mod monoid; +pub use monoid::*; + +mod monoidal_director; +pub use monoidal_director::*; + +mod monoidal_reducer; +pub use monoidal_reducer::*; diff --git a/asg/src/reducer/monoid/bool_and.rs b/asg/src/reducer/monoid/bool_and.rs new file mode 100644 index 0000000000..fde095e99d --- /dev/null +++ b/asg/src/reducer/monoid/bool_and.rs @@ -0,0 +1,40 @@ +// 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 . + +use super::*; + +pub struct BoolAnd(pub bool); + +impl Default for BoolAnd { + fn default() -> Self { + BoolAnd(false) + } +} + +impl Monoid for BoolAnd { + fn append(self, other: Self) -> Self { + BoolAnd(self.0 && other.0) + } + + fn append_all(self, others: impl Iterator) -> Self { + for item in others { + if !item.0 { + return BoolAnd(false); + } + } + BoolAnd(true) + } +} diff --git a/asg/src/reducer/monoid/mod.rs b/asg/src/reducer/monoid/mod.rs new file mode 100644 index 0000000000..7aac7f7d21 --- /dev/null +++ b/asg/src/reducer/monoid/mod.rs @@ -0,0 +1,43 @@ +// 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 . + +mod bool_and; +pub use bool_and::*; + +mod set_append; +pub use set_append::*; + +mod vec_append; +pub use vec_append::*; + +pub trait Monoid: Default { + fn append(self, other: Self) -> Self; + + fn append_all(self, others: impl Iterator) -> Self { + let mut current = self; + for item in others { + current = current.append(item); + } + current + } + + fn append_option(self, other: Option) -> Self { + match other { + None => self, + Some(other) => self.append(other), + } + } +} diff --git a/asg/src/reducer/monoid/set_append.rs b/asg/src/reducer/monoid/set_append.rs new file mode 100644 index 0000000000..49746a51bd --- /dev/null +++ b/asg/src/reducer/monoid/set_append.rs @@ -0,0 +1,51 @@ +// 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 . + +use super::*; + +use indexmap::IndexSet; +use std::hash::Hash; + +pub struct SetAppend(IndexSet); + +impl Default for SetAppend { + fn default() -> Self { + Self(IndexSet::new()) + } +} + +impl Monoid for SetAppend { + fn append(mut self, other: Self) -> Self { + self.0.extend(other.0); + SetAppend(self.0) + } + + fn append_all(mut self, others: impl Iterator) -> Self { + let all: Vec> = others.map(|x| x.0).collect(); + let total_size = all.iter().fold(0, |acc, v| acc + v.len()); + self.0.reserve(total_size); + for item in all.into_iter() { + self.0.extend(item); + } + self + } +} + +impl Into> for SetAppend { + fn into(self) -> IndexSet { + self.0 + } +} diff --git a/asg/src/reducer/monoid/vec_append.rs b/asg/src/reducer/monoid/vec_append.rs new file mode 100644 index 0000000000..f38dc6d1db --- /dev/null +++ b/asg/src/reducer/monoid/vec_append.rs @@ -0,0 +1,48 @@ +// 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 . + +use super::*; + +pub struct VecAppend(Vec); + +impl Default for VecAppend { + fn default() -> Self { + Self(vec![]) + } +} + +impl Monoid for VecAppend { + fn append(mut self, other: Self) -> Self { + self.0.extend(other.0); + VecAppend(self.0) + } + + fn append_all(mut self, others: impl Iterator) -> Self { + let all: Vec> = others.map(|x| x.0).collect(); + let total_size = all.iter().fold(0, |acc, v| acc + v.len()); + self.0.reserve(total_size); + for item in all.into_iter() { + self.0.extend(item); + } + self + } +} + +impl Into> for VecAppend { + fn into(self) -> Vec { + self.0 + } +} diff --git a/asg/src/reducer/monoidal_director.rs b/asg/src/reducer/monoidal_director.rs new file mode 100644 index 0000000000..15b26d08d7 --- /dev/null +++ b/asg/src/reducer/monoidal_director.rs @@ -0,0 +1,290 @@ +// 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 . + +use super::*; +use crate::{expression::*, program::*, statement::*}; + +use std::{marker::PhantomData, sync::Arc}; + +pub struct MonoidalDirector> { + reducer: R, + _monoid: PhantomData, +} + +impl> MonoidalDirector { + pub fn new(reducer: R) -> Self { + Self { + reducer, + _monoid: PhantomData, + } + } + + pub fn reducer(self) -> R { + self.reducer + } + + pub fn reduce_expression(&mut self, input: &Arc) -> T { + match &**input { + Expression::ArrayAccess(e) => self.reduce_array_access(e), + Expression::ArrayInit(e) => self.reduce_array_init(e), + Expression::ArrayInline(e) => self.reduce_array_inline(e), + Expression::ArrayRangeAccess(e) => self.reduce_array_range_access(e), + Expression::Binary(e) => self.reduce_binary(e), + Expression::Call(e) => self.reduce_call(e), + Expression::CircuitAccess(e) => self.reduce_circuit_access(e), + Expression::CircuitInit(e) => self.reduce_circuit_init(e), + Expression::Ternary(e) => self.reduce_ternary_expression(e), + Expression::Constant(e) => self.reduce_constant(e), + Expression::TupleAccess(e) => self.reduce_tuple_access(e), + Expression::TupleInit(e) => self.reduce_tuple_init(e), + Expression::Unary(e) => self.reduce_unary(e), + Expression::VariableRef(e) => self.reduce_variable_ref(e), + } + } + + pub fn reduce_array_access(&mut self, input: &ArrayAccessExpression) -> T { + let array = self.reduce_expression(&input.array); + let index = self.reduce_expression(&input.index); + + self.reducer.reduce_array_access(input, array, index) + } + + pub fn reduce_array_init(&mut self, input: &ArrayInitExpression) -> T { + let element = self.reduce_expression(&input.element); + + self.reducer.reduce_array_init(input, element) + } + + pub fn reduce_array_inline(&mut self, input: &ArrayInlineExpression) -> T { + let elements = input.elements.iter().map(|(x, _)| self.reduce_expression(x)).collect(); + + self.reducer.reduce_array_inline(input, elements) + } + + pub fn reduce_array_range_access(&mut self, input: &ArrayRangeAccessExpression) -> T { + let array = self.reduce_expression(&input.array); + let left = input.left.as_ref().map(|e| self.reduce_expression(e)); + let right = input.right.as_ref().map(|e| self.reduce_expression(e)); + + self.reducer.reduce_array_range_access(input, array, left, right) + } + + pub fn reduce_binary(&mut self, input: &BinaryExpression) -> T { + let left = self.reduce_expression(&input.left); + let right = self.reduce_expression(&input.right); + + self.reducer.reduce_binary(input, left, right) + } + + pub fn reduce_call(&mut self, input: &CallExpression) -> T { + let target = input.target.as_ref().map(|e| self.reduce_expression(e)); + let arguments = input.arguments.iter().map(|e| self.reduce_expression(e)).collect(); + + self.reducer.reduce_call(input, target, arguments) + } + + pub fn reduce_circuit_access(&mut self, input: &CircuitAccessExpression) -> T { + let target = input.target.as_ref().map(|e| self.reduce_expression(e)); + + self.reducer.reduce_circuit_access(input, target) + } + + pub fn reduce_circuit_init(&mut self, input: &CircuitInitExpression) -> T { + let values = input.values.iter().map(|(_, e)| self.reduce_expression(e)).collect(); + + self.reducer.reduce_circuit_init(input, values) + } + + pub fn reduce_ternary_expression(&mut self, input: &TernaryExpression) -> T { + let condition = self.reduce_expression(&input.condition); + let if_true = self.reduce_expression(&input.if_true); + let if_false = self.reduce_expression(&input.if_false); + + self.reducer + .reduce_ternary_expression(input, condition, if_true, if_false) + } + + pub fn reduce_constant(&mut self, input: &Constant) -> T { + self.reducer.reduce_constant(input) + } + + pub fn reduce_tuple_access(&mut self, input: &TupleAccessExpression) -> T { + let tuple_ref = self.reduce_expression(&input.tuple_ref); + + self.reducer.reduce_tuple_access(input, tuple_ref) + } + + pub fn reduce_tuple_init(&mut self, input: &TupleInitExpression) -> T { + let values = input.elements.iter().map(|e| self.reduce_expression(e)).collect(); + + self.reducer.reduce_tuple_init(input, values) + } + + pub fn reduce_unary(&mut self, input: &UnaryExpression) -> T { + let inner = self.reduce_expression(&input.inner); + + self.reducer.reduce_unary(input, inner) + } + + pub fn reduce_variable_ref(&mut self, input: &VariableRef) -> T { + self.reducer.reduce_variable_ref(input) + } +} + +impl> MonoidalDirector { + pub fn reduce_statement(&mut self, input: &Arc) -> T { + match &**input { + Statement::Assign(s) => self.reduce_assign(s), + Statement::Block(s) => self.reduce_block(s), + Statement::Conditional(s) => self.reduce_conditional_statement(s), + Statement::Console(s) => self.reduce_console(s), + Statement::Definition(s) => self.reduce_definition(s), + Statement::Expression(s) => self.reduce_expression_statement(s), + Statement::Iteration(s) => self.reduce_iteration(s), + Statement::Return(s) => self.reduce_return(s), + } + } + + pub fn reduce_assign_access(&mut self, input: &AssignAccess) -> T { + let (left, right) = match input { + AssignAccess::ArrayRange(left, right) => ( + left.as_ref().map(|e| self.reduce_expression(e)), + right.as_ref().map(|e| self.reduce_expression(e)), + ), + AssignAccess::ArrayIndex(index) => (Some(self.reduce_expression(index)), None), + _ => (None, None), + }; + + self.reducer.reduce_assign_access(input, left, right) + } + + pub fn reduce_assign(&mut self, input: &AssignStatement) -> T { + let accesses = input + .target_accesses + .iter() + .map(|x| self.reduce_assign_access(x)) + .collect(); + let value = self.reduce_expression(&input.value); + + self.reducer.reduce_assign(input, accesses, value) + } + + pub fn reduce_block(&mut self, input: &BlockStatement) -> T { + let statements = input.statements.iter().map(|x| self.reduce_statement(x)).collect(); + + self.reducer.reduce_block(input, statements) + } + + pub fn reduce_conditional_statement(&mut self, input: &ConditionalStatement) -> T { + let condition = self.reduce_expression(&input.condition); + let if_true = self.reduce_statement(&input.result); + let if_false = input.next.as_ref().map(|s| self.reduce_statement(s)); + + self.reducer + .reduce_conditional_statement(input, condition, if_true, if_false) + } + + pub fn reduce_formatted_string(&mut self, input: &FormattedString) -> T { + let parameters = input.parameters.iter().map(|e| self.reduce_expression(e)).collect(); + + self.reducer.reduce_formatted_string(input, parameters) + } + + pub fn reduce_console(&mut self, input: &ConsoleStatement) -> T { + let argument = match &input.function { + ConsoleFunction::Assert(e) => self.reduce_expression(e), + ConsoleFunction::Debug(f) | ConsoleFunction::Error(f) | ConsoleFunction::Log(f) => { + self.reduce_formatted_string(f) + } + }; + + self.reducer.reduce_console(input, argument) + } + + pub fn reduce_definition(&mut self, input: &DefinitionStatement) -> T { + let value = self.reduce_expression(&input.value); + + self.reducer.reduce_definition(input, value) + } + + pub fn reduce_expression_statement(&mut self, input: &ExpressionStatement) -> T { + let value = self.reduce_expression(&input.expression); + + self.reducer.reduce_expression_statement(input, value) + } + + pub fn reduce_iteration(&mut self, input: &IterationStatement) -> T { + let start = self.reduce_expression(&input.start); + let stop = self.reduce_expression(&input.stop); + let body = self.reduce_statement(&input.body); + + self.reducer.reduce_iteration(input, start, stop, body) + } + + pub fn reduce_return(&mut self, input: &ReturnStatement) -> T { + let value = self.reduce_expression(&input.expression); + + self.reducer.reduce_return(input, value) + } +} + +#[allow(dead_code)] +impl> MonoidalDirector { + fn reduce_function(&mut self, input: &Arc) -> T { + let body = self.reduce_statement(&input.body); + + self.reducer.reduce_function(input, body) + } + + fn reduce_circuit_member(&mut self, input: &CircuitMemberBody) -> T { + let function = match input { + CircuitMemberBody::Function(f) => Some(self.reduce_function(f)), + _ => None, + }; + + self.reducer.reduce_circuit_member(input, function) + } + + fn reduce_circuit(&mut self, input: &Arc) -> T { + let members = input + .members + .borrow() + .iter() + .map(|(_, member)| self.reduce_circuit_member(member)) + .collect(); + + self.reducer.reduce_circuit(input, members) + } + + fn reduce_program(&mut self, input: &Program) -> T { + let input = input.borrow(); + let imported_modules = input + .imported_modules + .iter() + .map(|(_, import)| self.reduce_program(import)) + .collect(); + let test_functions = input + .test_functions + .iter() + .map(|(_, (f, _))| self.reduce_function(f)) + .collect(); + let functions = input.functions.iter().map(|(_, f)| self.reduce_function(f)).collect(); + let circuits = input.circuits.iter().map(|(_, c)| self.reduce_circuit(c)).collect(); + + self.reducer + .reduce_program(&input, imported_modules, test_functions, functions, circuits) + } +} diff --git a/asg/src/reducer/monoidal_reducer.rs b/asg/src/reducer/monoidal_reducer.rs new file mode 100644 index 0000000000..1d5adef29d --- /dev/null +++ b/asg/src/reducer/monoidal_reducer.rs @@ -0,0 +1,172 @@ +// 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 . + +use crate::{expression::*, program::*, statement::*, Monoid}; + +use std::sync::Arc; + +#[allow(unused_variables)] +pub trait MonoidalReducerExpression { + fn reduce_expression(&mut self, input: &Arc, value: T) -> T { + value + } + + fn reduce_array_access(&mut self, input: &ArrayAccessExpression, array: T, index: T) -> T { + array.append(index) + } + + fn reduce_array_init(&mut self, input: &ArrayInitExpression, element: T) -> T { + element + } + + fn reduce_array_inline(&mut self, input: &ArrayInlineExpression, elements: Vec) -> T { + T::default().append_all(elements.into_iter()) + } + + fn reduce_array_range_access( + &mut self, + input: &ArrayRangeAccessExpression, + array: T, + left: Option, + right: Option, + ) -> T { + array.append_option(left).append_option(right) + } + + fn reduce_binary(&mut self, input: &BinaryExpression, left: T, right: T) -> T { + left.append(right) + } + + fn reduce_call(&mut self, input: &CallExpression, target: Option, arguments: Vec) -> T { + target.unwrap_or_default().append_all(arguments.into_iter()) + } + + fn reduce_circuit_access(&mut self, input: &CircuitAccessExpression, target: Option) -> T { + target.unwrap_or_default() + } + + fn reduce_circuit_init(&mut self, input: &CircuitInitExpression, values: Vec) -> T { + T::default().append_all(values.into_iter()) + } + + fn reduce_ternary_expression(&mut self, input: &TernaryExpression, condition: T, if_true: T, if_false: T) -> T { + condition.append(if_true).append(if_false) + } + + fn reduce_constant(&mut self, input: &Constant) -> T { + T::default() + } + + fn reduce_tuple_access(&mut self, input: &TupleAccessExpression, tuple_ref: T) -> T { + tuple_ref + } + + fn reduce_tuple_init(&mut self, input: &TupleInitExpression, values: Vec) -> T { + T::default().append_all(values.into_iter()) + } + + fn reduce_unary(&mut self, input: &UnaryExpression, inner: T) -> T { + inner + } + + fn reduce_variable_ref(&mut self, input: &VariableRef) -> T { + T::default() + } +} + +#[allow(unused_variables)] +pub trait MonoidalReducerStatement: MonoidalReducerExpression { + fn reduce_statement(&mut self, input: &Arc, value: T) -> T { + value + } + + // left = Some(ArrayIndex.0) always if AssignAccess::ArrayIndex. if member/tuple, always None + fn reduce_assign_access(&mut self, input: &AssignAccess, left: Option, right: Option) -> T { + left.unwrap_or_default().append_option(right) + } + + fn reduce_assign(&mut self, input: &AssignStatement, accesses: Vec, value: T) -> T { + T::default().append_all(accesses.into_iter()).append(value) + } + + fn reduce_block(&mut self, input: &BlockStatement, statements: Vec) -> T { + T::default().append_all(statements.into_iter()) + } + + fn reduce_conditional_statement( + &mut self, + input: &ConditionalStatement, + condition: T, + if_true: T, + if_false: Option, + ) -> T { + condition.append(if_true).append_option(if_false) + } + + fn reduce_formatted_string(&mut self, input: &FormattedString, parameters: Vec) -> T { + T::default().append_all(parameters.into_iter()) + } + + fn reduce_console(&mut self, input: &ConsoleStatement, argument: T) -> T { + argument + } + + fn reduce_definition(&mut self, input: &DefinitionStatement, value: T) -> T { + value + } + + fn reduce_expression_statement(&mut self, input: &ExpressionStatement, expression: T) -> T { + expression + } + + fn reduce_iteration(&mut self, input: &IterationStatement, start: T, stop: T, body: T) -> T { + start.append(stop).append(body) + } + + fn reduce_return(&mut self, input: &ReturnStatement, value: T) -> T { + value + } +} + +#[allow(unused_variables)] +pub trait MonoidalReducerProgram: MonoidalReducerStatement { + fn reduce_function(&mut self, input: &Arc, body: T) -> T { + body + } + + fn reduce_circuit_member(&mut self, input: &CircuitMemberBody, function: Option) -> T { + function.unwrap_or_default() + } + + fn reduce_circuit(&mut self, input: &Arc, members: Vec) -> T { + T::default().append_all(members.into_iter()) + } + + fn reduce_program( + &mut self, + input: &InnerProgram, + imported_modules: Vec, + test_functions: Vec, + functions: Vec, + circuits: Vec, + ) -> T { + T::default() + .append_all(imported_modules.into_iter()) + .append_all(test_functions.into_iter()) + .append_all(functions.into_iter()) + .append_all(circuits.into_iter()) + } +} diff --git a/asg/src/scope.rs b/asg/src/scope.rs new file mode 100644 index 0000000000..c50c5399ff --- /dev/null +++ b/asg/src/scope.rs @@ -0,0 +1,237 @@ +// 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 . + +use crate::{AsgConvertError, Circuit, Function, Input, Type, Variable}; + +use indexmap::IndexMap; +use std::{cell::RefCell, sync::Arc}; +use uuid::Uuid; + +/// An abstract data type that track the current bindings for variables, functions, and circuits. +pub struct InnerScope { + /// The unique id of the scope. + pub id: Uuid, + + /// The parent scope that this scope inherits. + pub parent_scope: Option, + + /// The function definition that this scope occurs in. + pub function: Option>, + + /// The circuit definition that this scope occurs in. + pub circuit_self: Option>, + + /// Maps variable name => variable. + pub variables: IndexMap, + + /// Maps function name => function. + pub functions: IndexMap>, + + /// Maps circuit name => circuit. + pub circuits: IndexMap>, + + /// The main input to the program. + pub input: Option, +} + +pub type Scope = Arc>; + +impl InnerScope { + /// + /// Returns a reference to the variable corresponding to the name. + /// + /// If the current scope did not have this name present, then the parent scope is checked. + /// If there is no parent scope, then `None` is returned. + /// + pub fn resolve_variable(&self, name: &str) -> Option { + if let Some(resolved) = self.variables.get(name) { + Some(resolved.clone()) + } else if let Some(resolved) = self.parent_scope.as_ref() { + if let Some(resolved) = resolved.borrow().resolve_variable(name) { + Some(resolved) + } else { + None + } + } else { + None + } + } + + /// + /// Returns a reference to the current function. + /// + /// If the current scope did not have a function present, then the parent scope is checked. + /// If there is no parent scope, then `None` is returned. + /// + pub fn resolve_current_function(&self) -> Option> { + if let Some(resolved) = self.function.as_ref() { + Some(resolved.clone()) + } else if let Some(resolved) = self.parent_scope.as_ref() { + if let Some(resolved) = resolved.borrow().resolve_current_function() { + Some(resolved) + } else { + None + } + } else { + None + } + } + + /// + /// Returns a reference to the current input. + /// + /// If the current scope did not have an input present, then the parent scope is checked. + /// If there is no parent scope, then `None` is returned. + /// + pub fn resolve_input(&self) -> Option { + if let Some(input) = self.input.as_ref() { + Some(input.clone()) + } else if let Some(resolved) = self.parent_scope.as_ref() { + if let Some(resolved) = resolved.borrow().resolve_input() { + Some(resolved) + } else { + None + } + } else { + None + } + } + + /// + /// Returns a reference to the function corresponding to the name. + /// + /// If the current scope did not have this name present, then the parent scope is checked. + /// If there is no parent scope, then `None` is returned. + /// + pub fn resolve_function(&self, name: &str) -> Option> { + if let Some(resolved) = self.functions.get(name) { + Some(resolved.clone()) + } else if let Some(resolved) = self.parent_scope.as_ref() { + if let Some(resolved) = resolved.borrow().resolve_function(name) { + Some(resolved) + } else { + None + } + } else { + None + } + } + + /// + /// Returns a reference to the circuit corresponding to the name. + /// + /// If the current scope did not have this name present, then the parent scope is checked. + /// If there is no parent scope, then `None` is returned. + /// + pub fn resolve_circuit(&self, name: &str) -> Option> { + if let Some(resolved) = self.circuits.get(name) { + Some(resolved.clone()) + } else if name == "Self" && self.circuit_self.is_some() { + self.circuit_self.clone() + } else if let Some(resolved) = self.parent_scope.as_ref() { + if let Some(resolved) = resolved.borrow().resolve_circuit(name) { + Some(resolved) + } else { + None + } + } else { + None + } + } + + /// + /// Returns a reference to the current circuit. + /// + /// If the current scope did not have a circuit self present, then the parent scope is checked. + /// If there is no parent scope, then `None` is returned. + /// + pub fn resolve_circuit_self(&self) -> Option> { + if let Some(resolved) = self.circuit_self.as_ref() { + Some(resolved.clone()) + } else if let Some(resolved) = self.parent_scope.as_ref() { + if let Some(resolved) = resolved.borrow().resolve_circuit_self() { + Some(resolved) + } else { + None + } + } else { + None + } + } + + /// + /// Returns a new scope given a parent scope. + /// + pub fn make_subscope(scope: &Scope) -> Scope { + Arc::new(RefCell::new(InnerScope { + id: Uuid::new_v4(), + parent_scope: Some(scope.clone()), + circuit_self: None, + variables: IndexMap::new(), + functions: IndexMap::new(), + circuits: IndexMap::new(), + function: None, + input: None, + })) + } + + /// + /// Returns the type returned by the current scope. + /// + pub fn resolve_ast_type(&self, type_: &leo_ast::Type) -> Result { + use leo_ast::Type::*; + Ok(match type_ { + Address => Type::Address, + Boolean => Type::Boolean, + Field => Type::Field, + Group => Type::Group, + IntegerType(int_type) => Type::Integer(int_type.clone()), + Array(sub_type, dimensions) => { + let mut item = Box::new(self.resolve_ast_type(&*sub_type)?); + for dimension in dimensions.0.iter().rev() { + let dimension = dimension + .value + .parse::() + .map_err(|_| AsgConvertError::parse_index_error())?; + item = Box::new(Type::Array(item, dimension)); + } + *item + } + Tuple(sub_types) => Type::Tuple( + sub_types + .iter() + .map(|x| self.resolve_ast_type(x)) + .collect::, AsgConvertError>>()?, + ), + Circuit(name) if name.name == "Self" => Type::Circuit( + self.circuit_self + .clone() + .ok_or_else(|| AsgConvertError::unresolved_circuit(&name.name, &name.span))?, + ), + Circuit(name) => Type::Circuit( + self.circuits + .get(&name.name) + .ok_or_else(|| AsgConvertError::unresolved_circuit(&name.name, &name.span))? + .clone(), + ), + SelfType => Type::Circuit( + self.circuit_self + .clone() + .ok_or_else(AsgConvertError::reference_self_outside_circuit)?, + ), + }) + } +} diff --git a/asg/src/statement/assign.rs b/asg/src/statement/assign.rs new file mode 100644 index 0000000000..08714689a1 --- /dev/null +++ b/asg/src/statement/assign.rs @@ -0,0 +1,267 @@ +// 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 . + +use crate::{ + AsgConvertError, + CircuitMember, + ConstInt, + ConstValue, + Expression, + ExpressionNode, + FromAst, + Identifier, + IntegerType, + Node, + PartialType, + Scope, + Span, + Statement, + Type, + Variable, +}; +pub use leo_ast::AssignOperation; +use leo_ast::AssigneeAccess as AstAssigneeAccess; + +use std::sync::{Arc, Weak}; + +pub enum AssignAccess { + ArrayRange(Option>, Option>), + ArrayIndex(Arc), + Tuple(usize), + Member(Identifier), +} + +pub struct AssignStatement { + pub parent: Option>, + pub span: Option, + pub operation: AssignOperation, + pub target_variable: Variable, + pub target_accesses: Vec, + pub value: Arc, +} + +impl Node for AssignStatement { + fn span(&self) -> Option<&Span> { + self.span.as_ref() + } +} + +impl FromAst for Arc { + fn from_ast( + scope: &Scope, + statement: &leo_ast::AssignStatement, + _expected_type: Option, + ) -> Result, AsgConvertError> { + let (name, span) = (&statement.assignee.identifier.name, &statement.assignee.identifier.span); + + let variable = if name == "input" { + if let Some(function) = scope.borrow().resolve_current_function() { + if !function.has_input { + return Err(AsgConvertError::unresolved_reference(name, span)); + } + } else { + return Err(AsgConvertError::unresolved_reference(name, span)); + } + if let Some(input) = scope.borrow().resolve_input() { + input.container + } else { + return Err(AsgConvertError::InternalError( + "attempted to reference input when none is in scope".to_string(), + )); + } + } else { + scope + .borrow() + .resolve_variable(&name) + .ok_or_else(|| AsgConvertError::unresolved_reference(name, span))? + }; + + if !variable.borrow().mutable { + return Err(AsgConvertError::immutable_assignment(&name, &statement.span)); + } + let mut target_type: Option = Some(variable.borrow().type_.clone().into()); + + let mut target_accesses = vec![]; + for access in statement.assignee.accesses.iter() { + target_accesses.push(match access { + AstAssigneeAccess::ArrayRange(left, right) => { + let index_type = Some(PartialType::Integer(None, Some(IntegerType::U32))); + let left = left + .as_ref() + .map( + |left: &leo_ast::Expression| -> Result, AsgConvertError> { + Arc::::from_ast(scope, left, index_type.clone()) + }, + ) + .transpose()?; + let right = right + .as_ref() + .map( + |right: &leo_ast::Expression| -> Result, AsgConvertError> { + Arc::::from_ast(scope, right, index_type) + }, + ) + .transpose()?; + + match &target_type { + Some(PartialType::Array(item, len)) => { + if let (Some(left), Some(right)) = ( + left.as_ref() + .map(|x| x.const_value()) + .unwrap_or_else(|| Some(ConstValue::Int(ConstInt::U32(0)))), + right + .as_ref() + .map(|x| x.const_value()) + .unwrap_or_else(|| Some(ConstValue::Int(ConstInt::U32(len.map(|x| x as u32)?)))), + ) { + let left = match left { + ConstValue::Int(x) => x.to_usize().ok_or_else(|| { + AsgConvertError::invalid_assign_index(&name, &x.to_string(), &statement.span) + })?, + _ => unimplemented!(), + }; + let right = match right { + ConstValue::Int(x) => x.to_usize().ok_or_else(|| { + AsgConvertError::invalid_assign_index(&name, &x.to_string(), &statement.span) + })?, + _ => unimplemented!(), + }; + if right >= left { + target_type = Some(PartialType::Array(item.clone(), Some((right - left) as usize))) + } else { + return Err(AsgConvertError::invalid_backwards_assignment( + &name, + left, + right, + &statement.span, + )); + } + } + } + _ => return Err(AsgConvertError::index_into_non_array(&name, &statement.span)), + } + + AssignAccess::ArrayRange(left, right) + } + AstAssigneeAccess::ArrayIndex(index) => { + target_type = match target_type.clone() { + Some(PartialType::Array(item, _)) => item.map(|x| *x), + _ => return Err(AsgConvertError::index_into_non_array(&name, &statement.span)), + }; + AssignAccess::ArrayIndex(Arc::::from_ast( + scope, + index, + Some(PartialType::Integer(None, Some(IntegerType::U32))), + )?) + } + AstAssigneeAccess::Tuple(index, _) => { + let index = index + .value + .parse::() + .map_err(|_| AsgConvertError::parse_index_error())?; + target_type = match target_type { + Some(PartialType::Tuple(types)) => types + .get(index) + .cloned() + .ok_or_else(|| AsgConvertError::tuple_index_out_of_bounds(index, &statement.span))?, + _ => return Err(AsgConvertError::index_into_non_tuple(&name, &statement.span)), + }; + AssignAccess::Tuple(index) + } + AstAssigneeAccess::Member(name) => { + target_type = match target_type { + Some(PartialType::Type(Type::Circuit(circuit))) => { + let circuit = circuit; + + let members = circuit.members.borrow(); + let member = members.get(&name.name).ok_or_else(|| { + AsgConvertError::unresolved_circuit_member( + &circuit.name.borrow().name, + &name.name, + &statement.span, + ) + })?; + + let x = match &member { + CircuitMember::Variable(type_) => type_.clone(), + CircuitMember::Function(_) => { + return Err(AsgConvertError::illegal_function_assign(&name.name, &statement.span)); + } + }; + Some(x.strong().partial()) + } + _ => { + return Err(AsgConvertError::index_into_non_tuple( + &statement.assignee.identifier.name, + &statement.span, + )); + } + }; + AssignAccess::Member(name.clone()) + } + }); + } + let value = Arc::::from_ast(scope, &statement.value, target_type)?; + + let statement = Arc::new(Statement::Assign(AssignStatement { + parent: None, + span: Some(statement.span.clone()), + operation: statement.operation.clone(), + target_variable: variable.clone(), + target_accesses, + value, + })); + + { + let mut variable = variable.borrow_mut(); + variable.assignments.push(Arc::downgrade(&statement)); + } + + Ok(statement) + } +} + +impl Into for &AssignStatement { + fn into(self) -> leo_ast::AssignStatement { + leo_ast::AssignStatement { + operation: self.operation.clone(), + assignee: leo_ast::Assignee { + identifier: self.target_variable.borrow().name.clone(), + accesses: self + .target_accesses + .iter() + .map(|access| match access { + AssignAccess::ArrayRange(left, right) => AstAssigneeAccess::ArrayRange( + left.as_ref().map(|e| e.as_ref().into()), + right.as_ref().map(|e| e.as_ref().into()), + ), + AssignAccess::ArrayIndex(index) => AstAssigneeAccess::ArrayIndex(index.as_ref().into()), + AssignAccess::Tuple(index) => AstAssigneeAccess::Tuple( + leo_ast::PositiveNumber { + value: index.to_string(), + }, + self.span.clone().unwrap_or_default(), + ), + AssignAccess::Member(name) => AstAssigneeAccess::Member(name.clone()), + }) + .collect(), + span: self.span.clone().unwrap_or_default(), + }, + value: self.value.as_ref().into(), + span: self.span.clone().unwrap_or_default(), + } + } +} diff --git a/asg/src/statement/block.rs b/asg/src/statement/block.rs new file mode 100644 index 0000000000..b715ca2f98 --- /dev/null +++ b/asg/src/statement/block.rs @@ -0,0 +1,66 @@ +// 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 . + +use crate::{AsgConvertError, FromAst, InnerScope, Node, PartialType, Scope, Span, Statement}; + +use std::sync::{Arc, Weak}; + +pub struct BlockStatement { + pub parent: Option>, + pub span: Option, + pub statements: Vec>, + pub scope: Scope, +} + +impl Node for BlockStatement { + fn span(&self) -> Option<&Span> { + self.span.as_ref() + } +} + +impl FromAst for BlockStatement { + fn from_ast( + scope: &Scope, + statement: &leo_ast::Block, + _expected_type: Option, + ) -> Result { + let new_scope = InnerScope::make_subscope(scope); + + let mut output = vec![]; + for item in statement.statements.iter() { + output.push(Arc::::from_ast(&new_scope, item, None)?); + } + Ok(BlockStatement { + parent: None, + span: Some(statement.span.clone()), + statements: output, + scope: new_scope, + }) + } +} + +impl Into for &BlockStatement { + fn into(self) -> leo_ast::Block { + leo_ast::Block { + statements: self + .statements + .iter() + .map(|statement| statement.as_ref().into()) + .collect(), + span: self.span.clone().unwrap_or_default(), + } + } +} diff --git a/asg/src/statement/conditional.rs b/asg/src/statement/conditional.rs new file mode 100644 index 0000000000..f1618d4db6 --- /dev/null +++ b/asg/src/statement/conditional.rs @@ -0,0 +1,75 @@ +// 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 . + +use crate::{AsgConvertError, BlockStatement, Expression, FromAst, Node, PartialType, Scope, Span, Statement, Type}; + +use std::sync::{Arc, Weak}; + +pub struct ConditionalStatement { + pub parent: Option>, + pub span: Option, + pub condition: Arc, + pub result: Arc, + pub next: Option>, +} + +impl Node for ConditionalStatement { + fn span(&self) -> Option<&Span> { + self.span.as_ref() + } +} + +impl FromAst for ConditionalStatement { + fn from_ast( + scope: &Scope, + statement: &leo_ast::ConditionalStatement, + _expected_type: Option, + ) -> Result { + let condition = Arc::::from_ast(scope, &statement.condition, Some(Type::Boolean.into()))?; + let result = Arc::new(Statement::Block(BlockStatement::from_ast( + scope, + &statement.block, + None, + )?)); + let next = statement + .next + .as_deref() + .map(|next| -> Result, AsgConvertError> { Arc::::from_ast(scope, next, None) }) + .transpose()?; + + Ok(ConditionalStatement { + parent: None, + span: Some(statement.span.clone()), + condition, + result, + next, + }) + } +} + +impl Into for &ConditionalStatement { + fn into(self) -> leo_ast::ConditionalStatement { + leo_ast::ConditionalStatement { + condition: self.condition.as_ref().into(), + block: match self.result.as_ref() { + Statement::Block(block) => block.into(), + _ => unimplemented!(), + }, + next: self.next.as_deref().map(|e| Box::new(e.into())), + span: self.span.clone().unwrap_or_default(), + } + } +} diff --git a/asg/src/statement/console.rs b/asg/src/statement/console.rs new file mode 100644 index 0000000000..05e4d06516 --- /dev/null +++ b/asg/src/statement/console.rs @@ -0,0 +1,133 @@ +// 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 . + +use crate::{AsgConvertError, Expression, FromAst, Node, PartialType, Scope, Span, Statement, Type}; +use leo_ast::ConsoleFunction as AstConsoleFunction; + +use std::sync::{Arc, Weak}; + +//todo: refactor to not require/depend on span +pub struct FormattedString { + pub string: String, + pub containers: Vec, + pub parameters: Vec>, + pub span: Span, +} + +pub enum ConsoleFunction { + Assert(Arc), + Debug(FormattedString), + Error(FormattedString), + Log(FormattedString), +} + +pub struct ConsoleStatement { + pub parent: Option>, + pub span: Option, + pub function: ConsoleFunction, +} + +impl Node for ConsoleStatement { + fn span(&self) -> Option<&Span> { + self.span.as_ref() + } +} + +impl FromAst for FormattedString { + fn from_ast( + scope: &Scope, + value: &leo_ast::FormattedString, + _expected_type: Option, + ) -> Result { + if value.parameters.len() != value.containers.len() { + // + 1 for formatting string as to not confuse user + return Err(AsgConvertError::unexpected_call_argument_count( + value.containers.len() + 1, + value.parameters.len() + 1, + &value.span, + )); + } + let mut parameters = vec![]; + for parameter in value.parameters.iter() { + parameters.push(Arc::::from_ast(scope, parameter, None)?); + } + Ok(FormattedString { + string: value.string.clone(), + containers: value.containers.iter().map(|x| x.span.clone()).collect(), + parameters, + span: value.span.clone(), + }) + } +} + +impl Into for &FormattedString { + fn into(self) -> leo_ast::FormattedString { + leo_ast::FormattedString { + string: self.string.clone(), + containers: self + .containers + .iter() + .map(|span| leo_ast::FormattedContainer { span: span.clone() }) + .collect(), + parameters: self.parameters.iter().map(|e| e.as_ref().into()).collect(), + span: self.span.clone(), + } + } +} + +impl FromAst for ConsoleStatement { + fn from_ast( + scope: &Scope, + statement: &leo_ast::ConsoleStatement, + _expected_type: Option, + ) -> Result { + Ok(ConsoleStatement { + parent: None, + span: Some(statement.span.clone()), + function: match &statement.function { + AstConsoleFunction::Assert(expression) => ConsoleFunction::Assert(Arc::::from_ast( + scope, + expression, + Some(Type::Boolean.into()), + )?), + AstConsoleFunction::Debug(formatted_string) => { + ConsoleFunction::Debug(FormattedString::from_ast(scope, formatted_string, None)?) + } + AstConsoleFunction::Error(formatted_string) => { + ConsoleFunction::Error(FormattedString::from_ast(scope, formatted_string, None)?) + } + AstConsoleFunction::Log(formatted_string) => { + ConsoleFunction::Log(FormattedString::from_ast(scope, formatted_string, None)?) + } + }, + }) + } +} + +impl Into for &ConsoleStatement { + fn into(self) -> leo_ast::ConsoleStatement { + use ConsoleFunction::*; + leo_ast::ConsoleStatement { + function: match &self.function { + Assert(e) => AstConsoleFunction::Assert(e.as_ref().into()), + Debug(formatted_string) => AstConsoleFunction::Debug(formatted_string.into()), + Error(formatted_string) => AstConsoleFunction::Error(formatted_string.into()), + Log(formatted_string) => AstConsoleFunction::Log(formatted_string.into()), + }, + span: self.span.clone().unwrap_or_default(), + } + } +} diff --git a/asg/src/statement/definition.rs b/asg/src/statement/definition.rs new file mode 100644 index 0000000000..a76fb264cb --- /dev/null +++ b/asg/src/statement/definition.rs @@ -0,0 +1,159 @@ +// 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 . + +use crate::{ + AsgConvertError, + Expression, + ExpressionNode, + FromAst, + InnerVariable, + Node, + PartialType, + Scope, + Span, + Statement, + Type, + Variable, +}; + +use std::{ + cell::RefCell, + sync::{Arc, Weak}, +}; + +pub struct DefinitionStatement { + pub parent: Option>, + pub span: Option, + pub variables: Vec, + pub value: Arc, +} + +impl Node for DefinitionStatement { + fn span(&self) -> Option<&Span> { + self.span.as_ref() + } +} + +impl FromAst for Arc { + fn from_ast( + scope: &Scope, + statement: &leo_ast::DefinitionStatement, + _expected_type: Option, + ) -> Result, AsgConvertError> { + let type_ = statement + .type_ + .as_ref() + .map(|x| scope.borrow().resolve_ast_type(&x)) + .transpose()?; + + let value = Arc::::from_ast(scope, &statement.value, type_.clone().map(Into::into))?; + + let type_ = type_.or_else(|| value.get_type()); + + let mut output_types = vec![]; + + let mut variables = vec![]; + if statement.variable_names.is_empty() { + return Err(AsgConvertError::illegal_ast_structure( + "cannot have 0 variable names in destructuring tuple", + )); + } + if statement.variable_names.len() == 1 { + // any return type is fine + output_types.push(type_); + } else { + // tuple destructure + match type_.as_ref() { + Some(Type::Tuple(sub_types)) if sub_types.len() == statement.variable_names.len() => { + output_types.extend(sub_types.clone().into_iter().map(Some).collect::>()); + } + type_ => { + return Err(AsgConvertError::unexpected_type( + &*format!("{}-ary tuple", statement.variable_names.len()), + type_.map(|x| x.to_string()).as_deref(), + &statement.span, + )); + } + } + } + + for (variable, type_) in statement.variable_names.iter().zip(output_types.into_iter()) { + if statement.declaration_type == leo_ast::Declare::Const && variable.mutable { + return Err(AsgConvertError::illegal_ast_structure("cannot have const mut")); + } + variables.push(Arc::new(RefCell::new(InnerVariable { + id: uuid::Uuid::new_v4(), + name: variable.identifier.clone(), + type_: type_ + .ok_or_else(|| AsgConvertError::unresolved_type(&variable.identifier.name, &statement.span))?, + mutable: variable.mutable, + declaration: crate::VariableDeclaration::Definition, + references: vec![], + assignments: vec![], + }))); + } + + { + let mut scope_borrow = scope.borrow_mut(); + for variable in variables.iter() { + scope_borrow + .variables + .insert(variable.borrow().name.name.clone(), variable.clone()); + } + } + + let statement = Arc::new(Statement::Definition(DefinitionStatement { + parent: None, + span: Some(statement.span.clone()), + variables: variables.clone(), + value, + })); + + variables.iter().for_each(|variable| { + variable.borrow_mut().assignments.push(Arc::downgrade(&statement)); + }); + + Ok(statement) + } +} + +impl Into for &DefinitionStatement { + fn into(self) -> leo_ast::DefinitionStatement { + assert!(!self.variables.is_empty()); + + let mut variable_names = vec![]; + let mut type_ = None::; + for variable in self.variables.iter() { + let variable = variable.borrow(); + variable_names.push(leo_ast::VariableName { + mutable: variable.mutable, + identifier: variable.name.clone(), + span: variable.name.span.clone(), + }); + if type_.is_none() { + type_ = Some((&variable.type_).into()); + } + } + + leo_ast::DefinitionStatement { + declaration_type: leo_ast::Declare::Let, + variable_names, + type_, + value: self.value.as_ref().into(), + span: self.span.clone().unwrap_or_default(), + } + } +} diff --git a/asg/src/statement/expression.rs b/asg/src/statement/expression.rs new file mode 100644 index 0000000000..a2655befdb --- /dev/null +++ b/asg/src/statement/expression.rs @@ -0,0 +1,56 @@ +// 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 . + +use crate::{AsgConvertError, Expression, FromAst, Node, PartialType, Scope, Span, Statement}; + +use std::sync::{Arc, Weak}; + +pub struct ExpressionStatement { + pub parent: Option>, + pub span: Option, + pub expression: Arc, +} + +impl Node for ExpressionStatement { + fn span(&self) -> Option<&Span> { + self.span.as_ref() + } +} + +impl FromAst for ExpressionStatement { + fn from_ast( + scope: &Scope, + statement: &leo_ast::ExpressionStatement, + _expected_type: Option, + ) -> Result { + let expression = Arc::::from_ast(scope, &statement.expression, None)?; + + Ok(ExpressionStatement { + parent: None, + span: Some(statement.span.clone()), + expression, + }) + } +} + +impl Into for &ExpressionStatement { + fn into(self) -> leo_ast::ExpressionStatement { + leo_ast::ExpressionStatement { + expression: self.expression.as_ref().into(), + span: self.span.clone().unwrap_or_default(), + } + } +} diff --git a/asg/src/statement/iteration.rs b/asg/src/statement/iteration.rs new file mode 100644 index 0000000000..183b98c626 --- /dev/null +++ b/asg/src/statement/iteration.rs @@ -0,0 +1,108 @@ +// 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 . + +use leo_ast::IntegerType; + +use crate::{ + AsgConvertError, + Expression, + ExpressionNode, + FromAst, + InnerVariable, + Node, + PartialType, + Scope, + Span, + Statement, + Variable, +}; + +use std::{ + cell::RefCell, + sync::{Arc, Weak}, +}; + +pub struct IterationStatement { + pub parent: Option>, + pub span: Option, + pub variable: Variable, + pub start: Arc, + pub stop: Arc, + pub body: Arc, +} + +impl Node for IterationStatement { + fn span(&self) -> Option<&Span> { + self.span.as_ref() + } +} + +impl FromAst for Arc { + fn from_ast( + scope: &Scope, + statement: &leo_ast::IterationStatement, + _expected_type: Option, + ) -> Result, AsgConvertError> { + let expected_index_type = Some(PartialType::Integer(None, Some(IntegerType::U32))); + let start = Arc::::from_ast(scope, &statement.start, expected_index_type.clone())?; + let stop = Arc::::from_ast(scope, &statement.stop, expected_index_type)?; + let variable = Arc::new(RefCell::new(InnerVariable { + id: uuid::Uuid::new_v4(), + name: statement.variable.clone(), + type_: start + .get_type() + .ok_or_else(|| AsgConvertError::unresolved_type(&statement.variable.name, &statement.span))?, + mutable: false, + declaration: crate::VariableDeclaration::IterationDefinition, + references: vec![], + assignments: vec![], + })); + scope + .borrow_mut() + .variables + .insert(statement.variable.name.clone(), variable.clone()); + + let statement = Arc::new(Statement::Iteration(IterationStatement { + parent: None, + span: Some(statement.span.clone()), + variable: variable.clone(), + stop, + start, + body: Arc::new(Statement::Block(crate::BlockStatement::from_ast( + scope, + &statement.block, + None, + )?)), + })); + variable.borrow_mut().assignments.push(Arc::downgrade(&statement)); + Ok(statement) + } +} + +impl Into for &IterationStatement { + fn into(self) -> leo_ast::IterationStatement { + leo_ast::IterationStatement { + variable: self.variable.borrow().name.clone(), + start: self.start.as_ref().into(), + stop: self.stop.as_ref().into(), + block: match self.body.as_ref() { + Statement::Block(block) => block.into(), + _ => unimplemented!(), + }, + span: self.span.clone().unwrap_or_default(), + } + } +} diff --git a/asg/src/statement/mod.rs b/asg/src/statement/mod.rs new file mode 100644 index 0000000000..51477a4532 --- /dev/null +++ b/asg/src/statement/mod.rs @@ -0,0 +1,114 @@ +// 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 . + +//! This module defines a statement node in an asg. +//! +//! Ast statement nodes can be directly converted into asg nodes with no major differences. + +mod assign; +pub use assign::*; + +mod block; +pub use block::*; + +mod conditional; +pub use conditional::*; + +mod console; +pub use console::*; + +mod definition; +pub use definition::*; + +mod expression; +pub use expression::*; + +mod iteration; +pub use iteration::*; + +mod return_; +pub use return_::*; + +use crate::{AsgConvertError, FromAst, Node, PartialType, Scope, Span}; + +use std::sync::Arc; + +pub enum Statement { + Return(ReturnStatement), + Definition(DefinitionStatement), + Assign(AssignStatement), + Conditional(ConditionalStatement), + Iteration(IterationStatement), + Console(ConsoleStatement), + Expression(ExpressionStatement), + Block(BlockStatement), +} + +impl Node for Statement { + fn span(&self) -> Option<&Span> { + use Statement::*; + match self { + Return(s) => s.span(), + Definition(s) => s.span(), + Assign(s) => s.span(), + Conditional(s) => s.span(), + Iteration(s) => s.span(), + Console(s) => s.span(), + Expression(s) => s.span(), + Block(s) => s.span(), + } + } +} + +impl FromAst for Arc { + fn from_ast( + scope: &Scope, + value: &leo_ast::Statement, + _expected_type: Option, + ) -> Result, AsgConvertError> { + use leo_ast::Statement::*; + Ok(match value { + Return(statement) => Arc::new(Statement::Return(ReturnStatement::from_ast(scope, statement, None)?)), + Definition(statement) => Arc::::from_ast(scope, statement, None)?, + Assign(statement) => Arc::::from_ast(scope, statement, None)?, + Conditional(statement) => Arc::new(Statement::Conditional(ConditionalStatement::from_ast( + scope, statement, None, + )?)), + Iteration(statement) => Arc::::from_ast(scope, statement, None)?, + Console(statement) => Arc::new(Statement::Console(ConsoleStatement::from_ast(scope, statement, None)?)), + Expression(statement) => Arc::new(Statement::Expression(ExpressionStatement::from_ast( + scope, statement, None, + )?)), + Block(statement) => Arc::new(Statement::Block(BlockStatement::from_ast(scope, statement, None)?)), + }) + } +} + +impl Into for &Statement { + fn into(self) -> leo_ast::Statement { + use Statement::*; + match self { + Return(statement) => leo_ast::Statement::Return(statement.into()), + Definition(statement) => leo_ast::Statement::Definition(statement.into()), + Assign(statement) => leo_ast::Statement::Assign(statement.into()), + Conditional(statement) => leo_ast::Statement::Conditional(statement.into()), + Iteration(statement) => leo_ast::Statement::Iteration(statement.into()), + Console(statement) => leo_ast::Statement::Console(statement.into()), + Expression(statement) => leo_ast::Statement::Expression(statement.into()), + Block(statement) => leo_ast::Statement::Block(statement.into()), + } + } +} diff --git a/asg/src/statement/return_.rs b/asg/src/statement/return_.rs new file mode 100644 index 0000000000..0ee87633df --- /dev/null +++ b/asg/src/statement/return_.rs @@ -0,0 +1,59 @@ +// 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 . + +use crate::{AsgConvertError, Expression, FromAst, Node, PartialType, Scope, Span, Statement, Type}; + +use std::sync::{Arc, Weak}; + +pub struct ReturnStatement { + pub parent: Option>, + pub span: Option, + pub expression: Arc, +} + +impl Node for ReturnStatement { + fn span(&self) -> Option<&Span> { + self.span.as_ref() + } +} + +impl FromAst for ReturnStatement { + fn from_ast( + scope: &Scope, + statement: &leo_ast::ReturnStatement, + _expected_type: Option, + ) -> Result { + let return_type: Option = scope + .borrow() + .resolve_current_function() + .map(|x| x.output.clone()) + .map(Into::into); + Ok(ReturnStatement { + parent: None, + span: Some(statement.span.clone()), + expression: Arc::::from_ast(scope, &statement.expression, return_type.map(Into::into))?, + }) + } +} + +impl Into for &ReturnStatement { + fn into(self) -> leo_ast::ReturnStatement { + leo_ast::ReturnStatement { + expression: self.expression.as_ref().into(), + span: self.span.clone().unwrap_or_default(), + } + } +} diff --git a/asg/src/type_.rs b/asg/src/type_.rs new file mode 100644 index 0000000000..67fb6eeb9d --- /dev/null +++ b/asg/src/type_.rs @@ -0,0 +1,246 @@ +// 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 . + +use crate::Circuit; +pub use leo_ast::IntegerType; + +use std::{ + fmt, + sync::{Arc, Weak}, +}; + +/// A type in an asg. +#[derive(Clone, PartialEq)] +pub enum Type { + // Data types + Address, + Boolean, + Field, + Group, + Integer(IntegerType), + + // Data type wrappers + Array(Box, usize), + Tuple(Vec), + Circuit(Arc), +} + +#[derive(Clone)] +pub enum WeakType { + Type(Type), // circuit not allowed + Circuit(Weak), +} + +#[derive(Clone, PartialEq)] +pub enum PartialType { + Type(Type), // non-array or tuple + Integer(Option, Option), // specific, context-specific + Array(Option>, Option), + Tuple(Vec>), +} + +impl Into for WeakType { + fn into(self) -> Type { + match self { + WeakType::Type(t) => t, + WeakType::Circuit(circuit) => Type::Circuit(circuit.upgrade().unwrap()), + } + } +} + +impl WeakType { + pub fn strong(self) -> Type { + self.into() + } + + pub fn is_unit(&self) -> bool { + matches!(self, WeakType::Type(Type::Tuple(t)) if t.is_empty()) + } +} + +impl Into for Type { + fn into(self) -> WeakType { + match self { + Type::Circuit(circuit) => WeakType::Circuit(Arc::downgrade(&circuit)), + t => WeakType::Type(t), + } + } +} + +impl Into> for PartialType { + fn into(self) -> Option { + match self { + PartialType::Type(t) => Some(t), + PartialType::Integer(sub_type, contextual_type) => Some(Type::Integer(sub_type.or(contextual_type)?)), + PartialType::Array(element, len) => Some(Type::Array(Box::new((*element?).full()?), len?)), + PartialType::Tuple(sub_types) => Some(Type::Tuple( + sub_types + .into_iter() + .map(|x| x.map(|x| x.full()).flatten()) + .collect::>>()?, + )), + } + } +} + +impl PartialType { + pub fn full(self) -> Option { + self.into() + } + + pub fn matches(&self, other: &Type) -> bool { + match (self, other) { + (PartialType::Type(t), other) => t.is_assignable_from(other), + (PartialType::Integer(self_sub_type, _), Type::Integer(sub_type)) => { + self_sub_type.as_ref().map(|x| x == sub_type).unwrap_or(true) + } + (PartialType::Array(element, len), Type::Array(other_element, other_len)) => { + if let Some(element) = element { + if !element.matches(&*other_element) { + return false; + } + } + if let Some(len) = len { + return len == other_len; + } + true + } + (PartialType::Tuple(sub_types), Type::Tuple(other_sub_types)) => { + // we dont enforce exact length for tuples here (relying on prior type checking) to allow for full-context-free tuple indexing + if sub_types.len() > other_sub_types.len() { + return false; + } + for (sub_type, other_sub_type) in sub_types.iter().zip(other_sub_types.iter()) { + if let Some(sub_type) = sub_type { + if !sub_type.matches(other_sub_type) { + return false; + } + } + } + true + } + _ => false, + } + } +} + +impl Into for Type { + fn into(self) -> PartialType { + match self { + Type::Integer(sub_type) => PartialType::Integer(Some(sub_type), None), + Type::Array(element, len) => PartialType::Array(Some(Box::new((*element).into())), Some(len)), + Type::Tuple(sub_types) => PartialType::Tuple(sub_types.into_iter().map(Into::into).map(Some).collect()), + x => PartialType::Type(x), + } + } +} + +impl Type { + pub fn is_assignable_from(&self, from: &Type) -> bool { + self == from + } + + pub fn partial(self) -> PartialType { + self.into() + } + + pub fn is_unit(&self) -> bool { + matches!(self, Type::Tuple(t) if t.is_empty()) + } +} + +impl fmt::Display for Type { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Type::Address => write!(f, "address"), + Type::Boolean => write!(f, "bool"), + Type::Field => write!(f, "field"), + Type::Group => write!(f, "group"), + Type::Integer(sub_type) => sub_type.fmt(f), + Type::Array(sub_type, len) => write!(f, "[{}; {}]", sub_type, len), + Type::Tuple(sub_types) => { + write!(f, "(")?; + for (i, sub_type) in sub_types.iter().enumerate() { + write!(f, "{}", sub_type)?; + if i < sub_types.len() - 1 { + write!(f, ", ")?; + } + } + write!(f, ")") + } + Type::Circuit(circuit) => write!(f, "{}", &circuit.name.borrow().name), + } + } +} + +impl fmt::Display for PartialType { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + PartialType::Type(t) => t.fmt(f), + PartialType::Integer(Some(sub_type), _) => write!(f, "{}", sub_type), + PartialType::Integer(_, Some(sub_type)) => write!(f, "<{}>", sub_type), + PartialType::Integer(_, _) => write!(f, "integer"), + PartialType::Array(sub_type, len) => { + write!(f, "[")?; + if let Some(sub_type) = sub_type { + write!(f, "{}", *sub_type)?; + } else { + write!(f, "?")?; + } + write!(f, "; ")?; + if let Some(len) = len { + write!(f, "{}", len)?; + } else { + write!(f, "?")?; + } + write!(f, "]") + } + PartialType::Tuple(sub_types) => { + write!(f, "(")?; + for (i, sub_type) in sub_types.iter().enumerate() { + if let Some(sub_type) = sub_type { + write!(f, "{}", *sub_type)?; + } else { + write!(f, "?")?; + } + if i < sub_types.len() - 1 { + write!(f, ", ")?; + } + } + write!(f, ")") + } + } + } +} + +impl Into for &Type { + fn into(self) -> leo_ast::Type { + use Type::*; + match self { + Address => leo_ast::Type::Address, + Boolean => leo_ast::Type::Boolean, + Field => leo_ast::Type::Field, + Group => leo_ast::Type::Group, + Integer(int_type) => leo_ast::Type::IntegerType(int_type.clone()), + Array(type_, len) => leo_ast::Type::Array( + Box::new(type_.as_ref().into()), + leo_ast::ArrayDimensions(vec![leo_ast::PositiveNumber { value: len.to_string() }]), + ), + Tuple(subtypes) => leo_ast::Type::Tuple(subtypes.iter().map(Into::into).collect()), + Circuit(circuit) => leo_ast::Type::Circuit(circuit.name.borrow().clone()), + } + } +} diff --git a/asg/src/variable.rs b/asg/src/variable.rs new file mode 100644 index 0000000000..3590556d72 --- /dev/null +++ b/asg/src/variable.rs @@ -0,0 +1,47 @@ +// 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 . + +use crate::{Expression, Statement, Type}; +use leo_ast::Identifier; + +use std::{ + cell::RefCell, + sync::{Arc, Weak}, +}; +use uuid::Uuid; + +/// Specifies how a program variable was declared. +#[derive(PartialEq)] +pub enum VariableDeclaration { + Definition, + IterationDefinition, + Parameter, + Input, +} + +/// Stores information on a program variable. +pub struct InnerVariable { + pub id: Uuid, + pub name: Identifier, + pub type_: Type, + pub mutable: bool, + pub declaration: VariableDeclaration, + pub references: Vec>, // all Expression::VariableRef or panic + pub assignments: Vec>, // all Statement::Assign or panic -- must be 1 if not mutable, or 0 if declaration == input | parameter +} + +pub type Variable = Arc>; +pub type WeakVariable = Weak>; diff --git a/asg/tests/fail/address/implicit_invalid.leo b/asg/tests/fail/address/implicit_invalid.leo new file mode 100644 index 0000000000..6f8eba5114 --- /dev/null +++ b/asg/tests/fail/address/implicit_invalid.leo @@ -0,0 +1,3 @@ +function main() { + let public_key_string: address = zleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8; +} \ No newline at end of file diff --git a/asg/tests/fail/address/mod.rs b/asg/tests/fail/address/mod.rs new file mode 100644 index 0000000000..b5b4cff3ea --- /dev/null +++ b/asg/tests/fail/address/mod.rs @@ -0,0 +1,39 @@ +// 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 . + +// 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 . + +use crate::load_asg; + +#[test] +fn test_implicit_invalid() { + let program_string = include_str!("implicit_invalid.leo"); + load_asg(program_string).err().unwrap(); +} diff --git a/asg/tests/fail/array/initializer_fail.leo b/asg/tests/fail/array/initializer_fail.leo new file mode 100644 index 0000000000..3b2e7785cc --- /dev/null +++ b/asg/tests/fail/array/initializer_fail.leo @@ -0,0 +1,3 @@ +function main(a: [u8; 3]) { + console.assert(a == [1u8; -3]); +} \ No newline at end of file diff --git a/asg/tests/fail/array/input_nested_3x2_fail.leo b/asg/tests/fail/array/input_nested_3x2_fail.leo new file mode 100644 index 0000000000..1f5bf7b334 --- /dev/null +++ b/asg/tests/fail/array/input_nested_3x2_fail.leo @@ -0,0 +1,3 @@ +function main(a: [u8; (3, 2)]) { + console.assert(a == [[0u8; 2]; 3)]); // This should be written the right way as this test is for the input file. +} diff --git a/asg/tests/fail/array/input_tuple_3x2_fail.leo b/asg/tests/fail/array/input_tuple_3x2_fail.leo new file mode 100644 index 0000000000..b84f26a97e --- /dev/null +++ b/asg/tests/fail/array/input_tuple_3x2_fail.leo @@ -0,0 +1,3 @@ +function main(a: [u8; (3, 2)]) { + console.assert(a == [0u8; (2, 3)]); +} diff --git a/asg/tests/fail/array/mod.rs b/asg/tests/fail/array/mod.rs new file mode 100644 index 0000000000..6f7b2fd19e --- /dev/null +++ b/asg/tests/fail/array/mod.rs @@ -0,0 +1,151 @@ +// 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 . + +// 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 . + +use crate::load_asg; + +// Expressions + +#[test] +fn test_initializer_fail() { + let program_string = include_str!("initializer_fail.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_input_nested_3x2_fail() { + let program_string = include_str!("input_nested_3x2_fail.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_input_tuple_3x2_fail() { + let program_string = include_str!("input_tuple_3x2_fail.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_multi_fail_initializer() { + let program_string = include_str!("multi_fail_initializer.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_multi_inline_fail() { + let program_string = include_str!("multi_fail_inline.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_multi_initializer_fail() { + let program_string = include_str!("multi_initializer_fail.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_nested_3x2_value_fail() { + let program_string = include_str!("nested_3x2_value_fail.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_tuple_3x2_value_fail() { + let program_string = include_str!("tuple_3x2_value_fail.leo"); + load_asg(program_string).err().unwrap(); +} + +// Array type tests + +#[test] +fn test_type_fail() { + let program_string = include_str!("type_fail.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_type_nested_value_nested_3x2_fail() { + let program_string = include_str!("type_nested_value_nested_3x2_fail.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_type_nested_value_nested_4x3x2_fail() { + let program_string = include_str!("type_nested_value_nested_4x3x2_fail.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_type_nested_value_tuple_3x2_fail() { + let program_string = include_str!("type_nested_value_tuple_3x2_fail.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_type_nested_value_tuple_4x3x2_fail() { + let program_string = include_str!("type_nested_value_tuple_4x3x2_fail.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_type_tuple_value_nested_3x2_fail() { + let program_string = include_str!("type_tuple_value_nested_3x2_fail.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_type_tuple_value_nested_3x2_swap_fail() { + let program_string = include_str!("type_tuple_value_nested_3x2_swap_fail.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_type_tuple_value_nested_4x3x2_fail() { + let program_string = include_str!("type_tuple_value_nested_4x3x2_fail.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_type_tuple_value_tuple_3x2_fail() { + let program_string = include_str!("type_tuple_value_tuple_3x2_fail.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_type_tuple_value_tuple_3x2_swap_fail() { + let program_string = include_str!("type_tuple_value_tuple_3x2_swap_fail.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_type_tuple_value_tuple_4x3x2_fail() { + let program_string = include_str!("type_tuple_value_tuple_4x3x2_fail.leo"); + load_asg(program_string).err().unwrap(); +} diff --git a/asg/tests/fail/array/multi_fail_initializer.leo b/asg/tests/fail/array/multi_fail_initializer.leo new file mode 100644 index 0000000000..258750b327 --- /dev/null +++ b/asg/tests/fail/array/multi_fail_initializer.leo @@ -0,0 +1,3 @@ +function main() { + let arr: [u8; (2, 2)] = [[1u8; 2]; 1]; // incorrect dimensions +} \ No newline at end of file diff --git a/asg/tests/fail/array/multi_fail_inline.leo b/asg/tests/fail/array/multi_fail_inline.leo new file mode 100644 index 0000000000..50a06c09b2 --- /dev/null +++ b/asg/tests/fail/array/multi_fail_inline.leo @@ -0,0 +1,4 @@ +function main() { + let arr: [u8; (2, 2)] = [[1u8, 1u8], + [1u8]]; // incorrect dimensions +} \ No newline at end of file diff --git a/asg/tests/fail/array/multi_initializer_fail.leo b/asg/tests/fail/array/multi_initializer_fail.leo new file mode 100644 index 0000000000..0bd76acffa --- /dev/null +++ b/asg/tests/fail/array/multi_initializer_fail.leo @@ -0,0 +1,3 @@ +function main() { + let arr: [u8; (2, 2)] = [1u8; (2, 1)]; // incorrect dimensions +} \ No newline at end of file diff --git a/asg/tests/fail/array/nested_3x2_value_fail.leo b/asg/tests/fail/array/nested_3x2_value_fail.leo new file mode 100644 index 0000000000..a187a51991 --- /dev/null +++ b/asg/tests/fail/array/nested_3x2_value_fail.leo @@ -0,0 +1,4 @@ +// Multidimensional array syntax in leo +function main() { + const a: [u32; (3, 2)] = [[0; 3]; 2]; // initializer (incorrectly reversed ordering) +} diff --git a/asg/tests/fail/array/tuple_3x2_value_fail.leo b/asg/tests/fail/array/tuple_3x2_value_fail.leo new file mode 100644 index 0000000000..78593ab696 --- /dev/null +++ b/asg/tests/fail/array/tuple_3x2_value_fail.leo @@ -0,0 +1,4 @@ +// Multidimensional array syntax in leo +function main() { + const a: [u32; (3, 2)] = [0; (2, 3)]; // initializer (incorrectly reversed ordering) +} diff --git a/asg/tests/fail/array/type_fail.leo b/asg/tests/fail/array/type_fail.leo new file mode 100644 index 0000000000..1402ceba4c --- /dev/null +++ b/asg/tests/fail/array/type_fail.leo @@ -0,0 +1,3 @@ +function main() { + let a: [u8; -2] = [0u32; 2]; +} \ No newline at end of file diff --git a/asg/tests/fail/array/type_nested_value_nested_3x2_fail.leo b/asg/tests/fail/array/type_nested_value_nested_3x2_fail.leo new file mode 100644 index 0000000000..56c8916fb0 --- /dev/null +++ b/asg/tests/fail/array/type_nested_value_nested_3x2_fail.leo @@ -0,0 +1,3 @@ +function main() { + const b: [[u8; 2]; 3] = [[0; 3]; 2]; // initializer (incorrectly reversed ordering) +} \ No newline at end of file diff --git a/asg/tests/fail/array/type_nested_value_nested_4x3x2_fail.leo b/asg/tests/fail/array/type_nested_value_nested_4x3x2_fail.leo new file mode 100644 index 0000000000..480327a91d --- /dev/null +++ b/asg/tests/fail/array/type_nested_value_nested_4x3x2_fail.leo @@ -0,0 +1,3 @@ +function main() { + const b: [[[u8; 2]; 3]; 4] = [[[0; 4]; 3]; 2]; // initializer (incorrectly reversed ordering) +} \ No newline at end of file diff --git a/asg/tests/fail/array/type_nested_value_tuple_3x2_fail.leo b/asg/tests/fail/array/type_nested_value_tuple_3x2_fail.leo new file mode 100644 index 0000000000..3bfb559615 --- /dev/null +++ b/asg/tests/fail/array/type_nested_value_tuple_3x2_fail.leo @@ -0,0 +1,3 @@ +function main() { + const b: [[u8; 2]; 3] = [0; (2, 3)]; // initializer (incorrectly reversed ordering) +} \ No newline at end of file diff --git a/asg/tests/fail/array/type_nested_value_tuple_4x3x2_fail.leo b/asg/tests/fail/array/type_nested_value_tuple_4x3x2_fail.leo new file mode 100644 index 0000000000..ce1219a37b --- /dev/null +++ b/asg/tests/fail/array/type_nested_value_tuple_4x3x2_fail.leo @@ -0,0 +1,3 @@ +function main() { + const b: [[[u8; 2]; 3]; 4] = [0; (2, 3, 4)]; // initializer (incorrectly reversed ordering) +} \ No newline at end of file diff --git a/asg/tests/fail/array/type_tuple_value_nested_3x2_fail.leo b/asg/tests/fail/array/type_tuple_value_nested_3x2_fail.leo new file mode 100644 index 0000000000..e84f025a9f --- /dev/null +++ b/asg/tests/fail/array/type_tuple_value_nested_3x2_fail.leo @@ -0,0 +1,3 @@ +function main() { + const b: [u8; (2, 3)] = [[0; 2]; 3]; // initializer (incorrectly reversed ordering) +} \ No newline at end of file diff --git a/asg/tests/fail/array/type_tuple_value_nested_3x2_swap_fail.leo b/asg/tests/fail/array/type_tuple_value_nested_3x2_swap_fail.leo new file mode 100644 index 0000000000..0b960c6b44 --- /dev/null +++ b/asg/tests/fail/array/type_tuple_value_nested_3x2_swap_fail.leo @@ -0,0 +1,7 @@ +function main() { + const a = [[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]]; // inline + + const b: [u8; (2, 3)] = [[0; 3]; 2]; // initializer + + console.assert(a == b); +} \ No newline at end of file diff --git a/asg/tests/fail/array/type_tuple_value_nested_4x3x2_fail.leo b/asg/tests/fail/array/type_tuple_value_nested_4x3x2_fail.leo new file mode 100644 index 0000000000..cbb7ccbf76 --- /dev/null +++ b/asg/tests/fail/array/type_tuple_value_nested_4x3x2_fail.leo @@ -0,0 +1,3 @@ +function main() { + const b: [u8; (4, 3, 2)] = [[[0; 4]; 3]; 2]; // initializer (incorrectly reversed ordering) +} \ No newline at end of file diff --git a/asg/tests/fail/array/type_tuple_value_tuple_3x2_fail.leo b/asg/tests/fail/array/type_tuple_value_tuple_3x2_fail.leo new file mode 100644 index 0000000000..884a75db9d --- /dev/null +++ b/asg/tests/fail/array/type_tuple_value_tuple_3x2_fail.leo @@ -0,0 +1,3 @@ +function main() { + const b: [u8; (2, 3)] = [0; (3, 2)]; // initializer (incorrectly reversed ordering) +} \ No newline at end of file diff --git a/asg/tests/fail/array/type_tuple_value_tuple_3x2_swap_fail.leo b/asg/tests/fail/array/type_tuple_value_tuple_3x2_swap_fail.leo new file mode 100644 index 0000000000..d742a544a7 --- /dev/null +++ b/asg/tests/fail/array/type_tuple_value_tuple_3x2_swap_fail.leo @@ -0,0 +1,7 @@ +function main() { + const a = [[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]]; // inline + + const b: [u8; (2, 3)] = [0; (2, 3)]; // initializer + + console.assert(a == b); +} \ No newline at end of file diff --git a/asg/tests/fail/array/type_tuple_value_tuple_4x3x2_fail.leo b/asg/tests/fail/array/type_tuple_value_tuple_4x3x2_fail.leo new file mode 100644 index 0000000000..31e2a5e552 --- /dev/null +++ b/asg/tests/fail/array/type_tuple_value_tuple_4x3x2_fail.leo @@ -0,0 +1,3 @@ +function main() { + const b: [u8; (4, 3, 2)] = [0; (2, 3, 4)]; // initializer (incorrectly reversed order) +} \ No newline at end of file diff --git a/asg/tests/fail/boolean/mod.rs b/asg/tests/fail/boolean/mod.rs new file mode 100644 index 0000000000..780ed3aa08 --- /dev/null +++ b/asg/tests/fail/boolean/mod.rs @@ -0,0 +1,51 @@ +// 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 . + +// 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 . + +use crate::load_asg; + +#[test] +fn test_not_u32() { + let program_string = include_str!("not_u32.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_true_or_u32() { + let program_string = include_str!("true_or_u32.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_true_and_u32() { + let program_string = include_str!("true_and_u32.leo"); + load_asg(program_string).err().unwrap(); +} diff --git a/asg/tests/fail/boolean/not_u32.leo b/asg/tests/fail/boolean/not_u32.leo new file mode 100644 index 0000000000..44491d785b --- /dev/null +++ b/asg/tests/fail/boolean/not_u32.leo @@ -0,0 +1,3 @@ +function main() -> bool { + console.assert(!1u32 == 0u32); +} \ No newline at end of file diff --git a/asg/tests/fail/boolean/true_and_u32.leo b/asg/tests/fail/boolean/true_and_u32.leo new file mode 100644 index 0000000000..e5b3a8c001 --- /dev/null +++ b/asg/tests/fail/boolean/true_and_u32.leo @@ -0,0 +1,3 @@ +function main() { + let a = true && 1u32; +} \ No newline at end of file diff --git a/asg/tests/fail/boolean/true_or_u32.leo b/asg/tests/fail/boolean/true_or_u32.leo new file mode 100644 index 0000000000..500b5f7bf4 --- /dev/null +++ b/asg/tests/fail/boolean/true_or_u32.leo @@ -0,0 +1,3 @@ +function main() { + let a = true || 1u32; +} \ No newline at end of file diff --git a/asg/tests/fail/circuits/inline_fail.leo b/asg/tests/fail/circuits/inline_fail.leo new file mode 100644 index 0000000000..52792a07e0 --- /dev/null +++ b/asg/tests/fail/circuits/inline_fail.leo @@ -0,0 +1,7 @@ +circuit Foo { + x: u32 +} + +function main() { + let a = Foo { y: 0u32 }; +} \ No newline at end of file diff --git a/asg/tests/fail/circuits/inline_undefined.leo b/asg/tests/fail/circuits/inline_undefined.leo new file mode 100644 index 0000000000..af070e01e9 --- /dev/null +++ b/asg/tests/fail/circuits/inline_undefined.leo @@ -0,0 +1,3 @@ +function main() { + let a = Foo { }; +} \ No newline at end of file diff --git a/asg/tests/fail/circuits/member_function_fail.leo b/asg/tests/fail/circuits/member_function_fail.leo new file mode 100644 index 0000000000..224b79cbf4 --- /dev/null +++ b/asg/tests/fail/circuits/member_function_fail.leo @@ -0,0 +1,10 @@ +circuit Foo { + function echo(x: u32) -> u32 { + return x + } +} + +function main() { + let a = Foo { }; + let err = a.echoed(1u32); +} \ No newline at end of file diff --git a/asg/tests/fail/circuits/member_function_invalid.leo b/asg/tests/fail/circuits/member_function_invalid.leo new file mode 100644 index 0000000000..bb834e9562 --- /dev/null +++ b/asg/tests/fail/circuits/member_function_invalid.leo @@ -0,0 +1,10 @@ +circuit Foo { + function echo(x: u32) -> u32 { + return x + } +} + +function main() { + let a = Foo { }; + let err = a.echo(1u32); // echo is a static function and must be accessed using `::` +} \ No newline at end of file diff --git a/asg/tests/fail/circuits/member_static_function_invalid.leo b/asg/tests/fail/circuits/member_static_function_invalid.leo new file mode 100644 index 0000000000..09fec386d9 --- /dev/null +++ b/asg/tests/fail/circuits/member_static_function_invalid.leo @@ -0,0 +1,9 @@ +circuit Foo { + function echo(x: u32) -> u32 { + return x + } +} + +function main() { + let err = Foo.echo(1u32); // Invalid, echo is a static function and must be accessed using `::` +} \ No newline at end of file diff --git a/asg/tests/fail/circuits/member_static_function_undefined.leo b/asg/tests/fail/circuits/member_static_function_undefined.leo new file mode 100644 index 0000000000..cf9f98c7b4 --- /dev/null +++ b/asg/tests/fail/circuits/member_static_function_undefined.leo @@ -0,0 +1,9 @@ +circuit Foo { + function echo(x: u32) -> u32 { + return x + } +} + +function main() { + let err = Foo::echoed(1u32); +} \ No newline at end of file diff --git a/asg/tests/fail/circuits/member_variable_fail.leo b/asg/tests/fail/circuits/member_variable_fail.leo new file mode 100644 index 0000000000..5780704ea2 --- /dev/null +++ b/asg/tests/fail/circuits/member_variable_fail.leo @@ -0,0 +1,9 @@ +circuit Foo { + x: u32 +} + +function main() { + let a = Foo { x: 1u32 }; + + let err = a.y; +} \ No newline at end of file diff --git a/asg/tests/fail/circuits/mod.rs b/asg/tests/fail/circuits/mod.rs new file mode 100644 index 0000000000..a9add5a7e1 --- /dev/null +++ b/asg/tests/fail/circuits/mod.rs @@ -0,0 +1,154 @@ +// 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 . + +// 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 . + +use crate::load_asg; + +// Expressions + +#[test] +fn test_inline_fail() { + let program_string = include_str!("inline_fail.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_inline_undefined() { + let program_string = include_str!("inline_undefined.leo"); + load_asg(program_string).err().unwrap(); +} + +// Members + +#[test] +fn test_member_variable_fail() { + let program_string = include_str!("member_variable_fail.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_member_function_fail() { + let program_string = include_str!("member_function_fail.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_member_function_invalid() { + let program_string = include_str!("member_function_invalid.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_mut_member_function_fail() { + let program_string = r#" + circuit Foo { + function echo(mut self, x: u32) -> u32 { + return x + } + } + + function main() { + let a = Foo { }; + + console.assert(a.echo(1u32) == 1u32); + }"#; + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_member_static_function_invalid() { + let program_string = include_str!("member_static_function_invalid.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_member_static_function_undefined() { + let program_string = include_str!("member_static_function_undefined.leo"); + load_asg(program_string).err().unwrap(); +} + +// Mutability + +#[test] +fn test_mutate_function_fail() { + let program_string = include_str!("mut_function_fail.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_mutate_self_variable_fail() { + let program_string = include_str!("mut_self_variable_fail.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_mutate_self_function_fail() { + let program_string = include_str!("mut_self_function_fail.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_mutate_self_static_function_fail() { + let program_string = include_str!("mut_self_static_function_fail.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_mutate_static_function_fail() { + let program_string = include_str!("mut_static_function_fail.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_mutate_variable_fail() { + let program_string = include_str!("mut_variable_fail.leo"); + load_asg(program_string).err().unwrap(); +} + +// Self + +#[test] +fn test_self_fail() { + let program_string = include_str!("self_fail.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_self_member_invalid() { + let program_string = include_str!("self_member_invalid.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_self_member_undefined() { + let program_string = include_str!("self_member_undefined.leo"); + load_asg(program_string).err().unwrap(); +} diff --git a/asg/tests/fail/circuits/mut_function_fail.leo b/asg/tests/fail/circuits/mut_function_fail.leo new file mode 100644 index 0000000000..3469f97627 --- /dev/null +++ b/asg/tests/fail/circuits/mut_function_fail.leo @@ -0,0 +1,11 @@ +circuit Foo { + a: u8, + + function bar() {} +} + +function main() { + let mut f = Foo { a: 0u8 }; + + f.bar = 1u8; +} \ No newline at end of file diff --git a/asg/tests/fail/circuits/mut_self_function_fail.leo b/asg/tests/fail/circuits/mut_self_function_fail.leo new file mode 100644 index 0000000000..8c9b99f6ae --- /dev/null +++ b/asg/tests/fail/circuits/mut_self_function_fail.leo @@ -0,0 +1,15 @@ +circuit Foo { + a: u8, + + function bar() {} + + function set_a(mut self, new: u8) { + self.bar = new; + } +} + +function main() { + let mut f = Foo { a: 0u8 }; + + f.set_a(1u8); +} \ No newline at end of file diff --git a/asg/tests/fail/circuits/mut_self_static_function_fail.leo b/asg/tests/fail/circuits/mut_self_static_function_fail.leo new file mode 100644 index 0000000000..8c9b99f6ae --- /dev/null +++ b/asg/tests/fail/circuits/mut_self_static_function_fail.leo @@ -0,0 +1,15 @@ +circuit Foo { + a: u8, + + function bar() {} + + function set_a(mut self, new: u8) { + self.bar = new; + } +} + +function main() { + let mut f = Foo { a: 0u8 }; + + f.set_a(1u8); +} \ No newline at end of file diff --git a/asg/tests/fail/circuits/mut_self_variable_fail.leo b/asg/tests/fail/circuits/mut_self_variable_fail.leo new file mode 100644 index 0000000000..fdbb556bca --- /dev/null +++ b/asg/tests/fail/circuits/mut_self_variable_fail.leo @@ -0,0 +1,13 @@ +circuit Foo { + a: u8, + + function set_a(self, new: u8) { + self.a = new; + } +} + +function main() { + let mut f = Foo { a: 0u8 }; + + f.set_a(1u8); +} \ No newline at end of file diff --git a/asg/tests/fail/circuits/mut_static_function_fail.leo b/asg/tests/fail/circuits/mut_static_function_fail.leo new file mode 100644 index 0000000000..ed3092c656 --- /dev/null +++ b/asg/tests/fail/circuits/mut_static_function_fail.leo @@ -0,0 +1,9 @@ +circuit Foo { + function bar() {} +} + +function main() { + let mut f = Foo { a: 0u8 }; + + f.bar = 1u8; +} \ No newline at end of file diff --git a/asg/tests/fail/circuits/mut_variable_fail.leo b/asg/tests/fail/circuits/mut_variable_fail.leo new file mode 100644 index 0000000000..4d58150c95 --- /dev/null +++ b/asg/tests/fail/circuits/mut_variable_fail.leo @@ -0,0 +1,9 @@ +circuit Foo { + a: u8, +} + +function main() { + let f = Foo { a: 0u8 }; + + f.a = 1u8; +} \ No newline at end of file diff --git a/asg/tests/fail/circuits/self_fail.leo b/asg/tests/fail/circuits/self_fail.leo new file mode 100644 index 0000000000..e4e878dc89 --- /dev/null +++ b/asg/tests/fail/circuits/self_fail.leo @@ -0,0 +1,3 @@ +function main() { + Self::main(); +} \ No newline at end of file diff --git a/asg/tests/fail/circuits/self_member_invalid.leo b/asg/tests/fail/circuits/self_member_invalid.leo new file mode 100644 index 0000000000..2e8b14f66c --- /dev/null +++ b/asg/tests/fail/circuits/self_member_invalid.leo @@ -0,0 +1,12 @@ +circuit Foo { + f: u32, + + function bar() -> u32 { + return f + } +} + +function main() -> u32 { + let foo = Foo { f: 1u32 }; + let err = foo.bar(); +} \ No newline at end of file diff --git a/asg/tests/fail/circuits/self_member_undefined.leo b/asg/tests/fail/circuits/self_member_undefined.leo new file mode 100644 index 0000000000..471ffb973c --- /dev/null +++ b/asg/tests/fail/circuits/self_member_undefined.leo @@ -0,0 +1,10 @@ +circuit Foo { + function bar() -> u32 { + return self.f + } +} + +function main() { + let foo = Foo { }; + let err = foo.bar(); +} \ No newline at end of file diff --git a/asg/tests/fail/console/assert.leo b/asg/tests/fail/console/assert.leo new file mode 100644 index 0000000000..ba6be77256 --- /dev/null +++ b/asg/tests/fail/console/assert.leo @@ -0,0 +1,3 @@ +function main(a: bool) { + console.assert(a == true); +} \ No newline at end of file diff --git a/asg/tests/fail/console/conditional_assert.leo b/asg/tests/fail/console/conditional_assert.leo new file mode 100644 index 0000000000..f2c1591e9c --- /dev/null +++ b/asg/tests/fail/console/conditional_assert.leo @@ -0,0 +1,7 @@ +function main(a: bool) { + if a { + console.assert(a == true); + } else { + console.assert(a == false); + } +} \ No newline at end of file diff --git a/asg/tests/fail/console/debug.leo b/asg/tests/fail/console/debug.leo new file mode 100644 index 0000000000..54e6eb539f --- /dev/null +++ b/asg/tests/fail/console/debug.leo @@ -0,0 +1,3 @@ +function main() { + console.debug("hello debug"); +} \ No newline at end of file diff --git a/asg/tests/fail/console/error.leo b/asg/tests/fail/console/error.leo new file mode 100644 index 0000000000..86d13f8cee --- /dev/null +++ b/asg/tests/fail/console/error.leo @@ -0,0 +1,3 @@ +function main() { + console.error("hello error"); +} \ No newline at end of file diff --git a/asg/tests/fail/console/log.leo b/asg/tests/fail/console/log.leo new file mode 100644 index 0000000000..a190ca4ba9 --- /dev/null +++ b/asg/tests/fail/console/log.leo @@ -0,0 +1,3 @@ +function main() { + console.log("hello world"); +} \ No newline at end of file diff --git a/asg/tests/fail/console/log_fail.leo b/asg/tests/fail/console/log_fail.leo new file mode 100644 index 0000000000..dafa6bea8e --- /dev/null +++ b/asg/tests/fail/console/log_fail.leo @@ -0,0 +1,3 @@ +function main() { + console.log( hello ); +} \ No newline at end of file diff --git a/asg/tests/fail/console/log_input.leo b/asg/tests/fail/console/log_input.leo new file mode 100644 index 0000000000..c4fd0a8b12 --- /dev/null +++ b/asg/tests/fail/console/log_input.leo @@ -0,0 +1,3 @@ +function main(a: bool) { + console.log("a = {}", a); +} \ No newline at end of file diff --git a/asg/tests/fail/console/log_parameter.leo b/asg/tests/fail/console/log_parameter.leo new file mode 100644 index 0000000000..ebcb931a2b --- /dev/null +++ b/asg/tests/fail/console/log_parameter.leo @@ -0,0 +1,3 @@ +function main() { + console.log("{}", 1u32); +} \ No newline at end of file diff --git a/asg/tests/fail/console/log_parameter_fail_empty.leo b/asg/tests/fail/console/log_parameter_fail_empty.leo new file mode 100644 index 0000000000..81b42c0919 --- /dev/null +++ b/asg/tests/fail/console/log_parameter_fail_empty.leo @@ -0,0 +1,3 @@ +function main() { + console.log("{}"); +} \ No newline at end of file diff --git a/asg/tests/fail/console/log_parameter_fail_none.leo b/asg/tests/fail/console/log_parameter_fail_none.leo new file mode 100644 index 0000000000..c92fdfbb2d --- /dev/null +++ b/asg/tests/fail/console/log_parameter_fail_none.leo @@ -0,0 +1,3 @@ +function main() { + console.log("", 1u32); +} \ No newline at end of file diff --git a/asg/tests/fail/console/log_parameter_fail_unknown.leo b/asg/tests/fail/console/log_parameter_fail_unknown.leo new file mode 100644 index 0000000000..757f4c27c3 --- /dev/null +++ b/asg/tests/fail/console/log_parameter_fail_unknown.leo @@ -0,0 +1,3 @@ +function main() { + console.log("{}", a); +} \ No newline at end of file diff --git a/asg/tests/fail/console/log_parameter_many.leo b/asg/tests/fail/console/log_parameter_many.leo new file mode 100644 index 0000000000..60455ebbb0 --- /dev/null +++ b/asg/tests/fail/console/log_parameter_many.leo @@ -0,0 +1,3 @@ +function main() { + console.log("{} {}", 1u32, true); +} \ No newline at end of file diff --git a/asg/tests/fail/console/mod.rs b/asg/tests/fail/console/mod.rs new file mode 100644 index 0000000000..f6dc483fe1 --- /dev/null +++ b/asg/tests/fail/console/mod.rs @@ -0,0 +1,57 @@ +// 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 . + +// 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 . + +use crate::load_asg; + +#[test] +fn test_log_fail() { + let program_string = include_str!("log_fail.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_log_parameter_fail_unknown() { + let program_string = include_str!("log_parameter_fail_unknown.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_log_parameter_fail_empty() { + let program_string = include_str!("log_parameter_fail_empty.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_log_parameter_fail_none() { + let program_string = include_str!("log_parameter_fail_empty.leo"); + load_asg(program_string).err().unwrap(); +} diff --git a/asg/tests/fail/core/core_circuit_invalid.leo b/asg/tests/fail/core/core_circuit_invalid.leo new file mode 100644 index 0000000000..4a42bda032 --- /dev/null +++ b/asg/tests/fail/core/core_circuit_invalid.leo @@ -0,0 +1,3 @@ +import core.unstable.blake2s.BadCircuit; // `BadCircuit` is not included in the blake2s package + +function main() {} diff --git a/asg/tests/fail/core/core_circuit_star_fail.leo b/asg/tests/fail/core/core_circuit_star_fail.leo new file mode 100644 index 0000000000..14b54b0d69 --- /dev/null +++ b/asg/tests/fail/core/core_circuit_star_fail.leo @@ -0,0 +1,3 @@ +import core.*; // You cannot import all dependencies from core at once + +function main() {} diff --git a/asg/tests/fail/core/core_package_invalid.leo b/asg/tests/fail/core/core_package_invalid.leo new file mode 100644 index 0000000000..7cbcf93ecc --- /dev/null +++ b/asg/tests/fail/core/core_package_invalid.leo @@ -0,0 +1,3 @@ +import core.bad_circuit; // `bad_circuit` is not a core package + +function main() {} diff --git a/asg/tests/fail/core/core_unstable_package_invalid.leo b/asg/tests/fail/core/core_unstable_package_invalid.leo new file mode 100644 index 0000000000..35e6c0d1ba --- /dev/null +++ b/asg/tests/fail/core/core_unstable_package_invalid.leo @@ -0,0 +1,3 @@ +import core.unstable.bad_circuit; // `bad_circuit` is not a core unstable package + +function main() {} diff --git a/asg/tests/fail/core/mod.rs b/asg/tests/fail/core/mod.rs new file mode 100644 index 0000000000..9ab7bb52bc --- /dev/null +++ b/asg/tests/fail/core/mod.rs @@ -0,0 +1,57 @@ +// 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 . + +// 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 . + +use crate::load_asg; + +#[test] +fn test_core_circuit_invalid() { + let program_string = include_str!("core_package_invalid.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_core_circuit_star_fail() { + let program_string = include_str!("core_circuit_star_fail.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_core_package_invalid() { + let program_string = include_str!("core_package_invalid.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_core_unstable_package_invalid() { + let program_string = include_str!("core_unstable_package_invalid.leo"); + load_asg(program_string).err().unwrap(); +} diff --git a/asg/tests/fail/definition/mod.rs b/asg/tests/fail/definition/mod.rs new file mode 100644 index 0000000000..e946846b69 --- /dev/null +++ b/asg/tests/fail/definition/mod.rs @@ -0,0 +1,31 @@ +// 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 . + +// 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 . diff --git a/asg/tests/fail/field/mod.rs b/asg/tests/fail/field/mod.rs new file mode 100644 index 0000000000..e946846b69 --- /dev/null +++ b/asg/tests/fail/field/mod.rs @@ -0,0 +1,31 @@ +// 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 . + +// 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 . diff --git a/asg/tests/fail/function/array_input.leo b/asg/tests/fail/function/array_input.leo new file mode 100644 index 0000000000..a70483cae7 --- /dev/null +++ b/asg/tests/fail/function/array_input.leo @@ -0,0 +1,6 @@ +function foo(a: [u8; 1]) {} + +function main() { + let a: [u16; 1] = [1; 1]; + foo(a); +} \ No newline at end of file diff --git a/asg/tests/fail/function/empty.leo b/asg/tests/fail/function/empty.leo new file mode 100644 index 0000000000..f06c976158 --- /dev/null +++ b/asg/tests/fail/function/empty.leo @@ -0,0 +1,5 @@ +function empty() { } + +function main() { + empty(); +} \ No newline at end of file diff --git a/asg/tests/fail/function/mod.rs b/asg/tests/fail/function/mod.rs new file mode 100644 index 0000000000..3156e3b580 --- /dev/null +++ b/asg/tests/fail/function/mod.rs @@ -0,0 +1,83 @@ +// 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 . + +// 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 . + +use crate::load_asg; + +#[test] +fn test_multiple_returns_fail() { + let program_string = include_str!("multiple_returns_fail.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_multiple_returns_input_ambiguous() { + let program_string = include_str!("multiple_returns_input_ambiguous.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_multiple_returns_fail_conditional() { + let program_string = include_str!("multiple_returns_fail_conditional.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_scope_fail() { + let program_string = include_str!("scope_fail.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_undefined() { + let program_string = include_str!("undefined.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_array_input() { + let program_string = include_str!("array_input.leo"); + load_asg(program_string).err().unwrap(); +} + +// Test return multidimensional arrays + +#[test] +fn test_return_array_nested_fail() { + let program_string = include_str!("return_array_nested_fail.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_return_array_tuple_fail() { + let program_string = include_str!("return_array_tuple_fail.leo"); + load_asg(program_string).err().unwrap(); +} diff --git a/asg/tests/fail/function/multiple_returns_fail.leo b/asg/tests/fail/function/multiple_returns_fail.leo new file mode 100644 index 0000000000..d4a8b36eac --- /dev/null +++ b/asg/tests/fail/function/multiple_returns_fail.leo @@ -0,0 +1,7 @@ +function main () -> i8 { + if true { + return 1i8 //ignored + } + return 2i8 //ignored + return 3i8 //returns +} \ No newline at end of file diff --git a/asg/tests/fail/function/multiple_returns_fail_conditional.leo b/asg/tests/fail/function/multiple_returns_fail_conditional.leo new file mode 100644 index 0000000000..04ebb9e306 --- /dev/null +++ b/asg/tests/fail/function/multiple_returns_fail_conditional.leo @@ -0,0 +1,9 @@ +function main () -> u16 { + if false { + let a = 1u16; + let b = a + 1u16; + return b + } else if false { + return 0u16 + } +} \ No newline at end of file diff --git a/asg/tests/fail/function/multiple_returns_input_ambiguous.leo b/asg/tests/fail/function/multiple_returns_input_ambiguous.leo new file mode 100644 index 0000000000..234375349b --- /dev/null +++ b/asg/tests/fail/function/multiple_returns_input_ambiguous.leo @@ -0,0 +1,7 @@ +function main(input) -> u32 { + if input.registers.a == 0 { + return 0u32 + } else { + return 1u32 + } +} \ No newline at end of file diff --git a/asg/tests/fail/function/return_array_nested_fail.leo b/asg/tests/fail/function/return_array_nested_fail.leo new file mode 100644 index 0000000000..dca001d9cc --- /dev/null +++ b/asg/tests/fail/function/return_array_nested_fail.leo @@ -0,0 +1,7 @@ +function array_3x2_tuple() -> [[u8; 2]; 3] { + return [0u8; (2, 3)] // The correct 3x2 array tuple is `[0u8; (3, 2)]` +} + +function main() { + let b = array_3x2_tuple(); +} \ No newline at end of file diff --git a/asg/tests/fail/function/return_array_tuple_fail.leo b/asg/tests/fail/function/return_array_tuple_fail.leo new file mode 100644 index 0000000000..4b7377e327 --- /dev/null +++ b/asg/tests/fail/function/return_array_tuple_fail.leo @@ -0,0 +1,7 @@ +function array_3x2_nested() -> [u8; (3, 2)] { + return [[0u8; 3]; 2] // The correct 3x2 nested array is `[0u8; 2]; 3]` +} + +function main() { + let a = array_3x2_nested(); +} \ No newline at end of file diff --git a/asg/tests/fail/function/scope_fail.leo b/asg/tests/fail/function/scope_fail.leo new file mode 100644 index 0000000000..ac6bfcad37 --- /dev/null +++ b/asg/tests/fail/function/scope_fail.leo @@ -0,0 +1,8 @@ +function foo() -> field { + return myGlobal +} + +function main() { + const myGlobal = 42field; + let err = foo(); +} \ No newline at end of file diff --git a/asg/tests/fail/function/undefined.leo b/asg/tests/fail/function/undefined.leo new file mode 100644 index 0000000000..e1db3b9f09 --- /dev/null +++ b/asg/tests/fail/function/undefined.leo @@ -0,0 +1,3 @@ +function main() { + my_function(); +} \ No newline at end of file diff --git a/asg/tests/fail/group/both_sign_high.leo b/asg/tests/fail/group/both_sign_high.leo new file mode 100644 index 0000000000..a8217d6d40 --- /dev/null +++ b/asg/tests/fail/group/both_sign_high.leo @@ -0,0 +1,3 @@ +function main() { + let element = (+, +)group; +} \ No newline at end of file diff --git a/asg/tests/fail/group/both_sign_inferred.leo b/asg/tests/fail/group/both_sign_inferred.leo new file mode 100644 index 0000000000..b3b8b512c3 --- /dev/null +++ b/asg/tests/fail/group/both_sign_inferred.leo @@ -0,0 +1,3 @@ +function main() { + let element = (_, _)group; +} \ No newline at end of file diff --git a/asg/tests/fail/group/both_sign_low.leo b/asg/tests/fail/group/both_sign_low.leo new file mode 100644 index 0000000000..0519c6d17d --- /dev/null +++ b/asg/tests/fail/group/both_sign_low.leo @@ -0,0 +1,3 @@ +function main() { + let element = (-, -)group; +} \ No newline at end of file diff --git a/asg/tests/fail/group/mod.rs b/asg/tests/fail/group/mod.rs new file mode 100644 index 0000000000..f8e29728ce --- /dev/null +++ b/asg/tests/fail/group/mod.rs @@ -0,0 +1,52 @@ +// 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 . + +// 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 . + +use crate::load_asg; + +#[test] +fn test_both_sign_high() { + let program_string = include_str!("both_sign_high.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_both_sign_low() { + let program_string = include_str!("both_sign_low.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_both_sign_inferred() { + let program_string = include_str!("both_sign_inferred.leo"); + load_asg(program_string).err().unwrap(); + +} diff --git a/asg/tests/fail/import/mod.rs b/asg/tests/fail/import/mod.rs new file mode 100644 index 0000000000..e946846b69 --- /dev/null +++ b/asg/tests/fail/import/mod.rs @@ -0,0 +1,31 @@ +// 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 . + +// 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 . diff --git a/asg/tests/fail/integers/i128/max_fail.leo b/asg/tests/fail/integers/i128/max_fail.leo new file mode 100644 index 0000000000..820eda8759 --- /dev/null +++ b/asg/tests/fail/integers/i128/max_fail.leo @@ -0,0 +1,3 @@ +function main() { + let a: i128 = 170141183460469231731687303715884105728; +} \ No newline at end of file diff --git a/asg/tests/fail/integers/i128/min_fail.leo b/asg/tests/fail/integers/i128/min_fail.leo new file mode 100644 index 0000000000..9035444fa9 --- /dev/null +++ b/asg/tests/fail/integers/i128/min_fail.leo @@ -0,0 +1,3 @@ +function main() { + let a: i128 = -170141183460469231731687303715884105729; +} \ No newline at end of file diff --git a/asg/tests/fail/integers/i128/mod.rs b/asg/tests/fail/integers/i128/mod.rs new file mode 100644 index 0000000000..2062617fdf --- /dev/null +++ b/asg/tests/fail/integers/i128/mod.rs @@ -0,0 +1,50 @@ +// 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 . + +// 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 . + +use super::IntegerTester; + +test_int!(TestI128); + +#[test] +fn test_i128_min_fail() { + TestI128::test_min_fail(); +} + +#[test] +fn test_i128_max_fail() { + TestI128::test_max_fail(); +} + +// #[test] +// fn test_i128_neg_max_fail() { +// TestI128::test_negate_min_fail(); +// } diff --git a/asg/tests/fail/integers/i128/negate_min.leo b/asg/tests/fail/integers/i128/negate_min.leo new file mode 100644 index 0000000000..cfbd308362 --- /dev/null +++ b/asg/tests/fail/integers/i128/negate_min.leo @@ -0,0 +1,4 @@ +function main() { + let a: i128 = -170141183460469231731687303715884105728; + let b = -a; +} \ No newline at end of file diff --git a/asg/tests/fail/integers/i16/max_fail.leo b/asg/tests/fail/integers/i16/max_fail.leo new file mode 100644 index 0000000000..8dd2b7f50a --- /dev/null +++ b/asg/tests/fail/integers/i16/max_fail.leo @@ -0,0 +1,3 @@ +function main() { + let a: i16 = 32768; +} \ No newline at end of file diff --git a/asg/tests/fail/integers/i16/min_fail.leo b/asg/tests/fail/integers/i16/min_fail.leo new file mode 100644 index 0000000000..380848381a --- /dev/null +++ b/asg/tests/fail/integers/i16/min_fail.leo @@ -0,0 +1,3 @@ +function main() { + let a: i16 = -32769; +} \ No newline at end of file diff --git a/asg/tests/fail/integers/i16/mod.rs b/asg/tests/fail/integers/i16/mod.rs new file mode 100644 index 0000000000..a60934189f --- /dev/null +++ b/asg/tests/fail/integers/i16/mod.rs @@ -0,0 +1,50 @@ +// 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 . + +// 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 . + +use super::IntegerTester; + +test_int!(TestI16); + +#[test] +fn test_i16_min_fail() { + TestI16::test_min_fail(); +} + +#[test] +fn test_i16_max_fail() { + TestI16::test_max_fail(); +} + +// #[test] +// fn test_i16_neg_max_fail() { +// TestI16::test_negate_min_fail(); +// } diff --git a/asg/tests/fail/integers/i16/negate_min.leo b/asg/tests/fail/integers/i16/negate_min.leo new file mode 100644 index 0000000000..2622f8d2a3 --- /dev/null +++ b/asg/tests/fail/integers/i16/negate_min.leo @@ -0,0 +1,4 @@ +function main() { + let a = -32768i16; + let b = -a; +} \ No newline at end of file diff --git a/asg/tests/fail/integers/i32/max_fail.leo b/asg/tests/fail/integers/i32/max_fail.leo new file mode 100644 index 0000000000..f3fd81815f --- /dev/null +++ b/asg/tests/fail/integers/i32/max_fail.leo @@ -0,0 +1,3 @@ +function main() { + let a: i32 = 2147483648; +} \ No newline at end of file diff --git a/asg/tests/fail/integers/i32/min_fail.leo b/asg/tests/fail/integers/i32/min_fail.leo new file mode 100644 index 0000000000..1462d207e9 --- /dev/null +++ b/asg/tests/fail/integers/i32/min_fail.leo @@ -0,0 +1,3 @@ +function main() { + let a: i32 = -2147483649; +} \ No newline at end of file diff --git a/asg/tests/fail/integers/i32/mod.rs b/asg/tests/fail/integers/i32/mod.rs new file mode 100644 index 0000000000..fcae16f93e --- /dev/null +++ b/asg/tests/fail/integers/i32/mod.rs @@ -0,0 +1,50 @@ +// 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 . + +// 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 . + +use super::IntegerTester; + +test_int!(TestI32); + +#[test] +fn test_i32_min_fail() { + TestI32::test_min_fail(); +} + +#[test] +fn test_i32_max_fail() { + TestI32::test_max_fail(); +} + +// #[test] +// fn test_i32_neg_max_fail() { +// TestI32::test_negate_min_fail(); +// } diff --git a/asg/tests/fail/integers/i32/negate_min.leo b/asg/tests/fail/integers/i32/negate_min.leo new file mode 100644 index 0000000000..b3c10064e1 --- /dev/null +++ b/asg/tests/fail/integers/i32/negate_min.leo @@ -0,0 +1,4 @@ +function main() { + let a = -2147483648i32; + let b = -a; +} \ No newline at end of file diff --git a/asg/tests/fail/integers/i64/max_fail.leo b/asg/tests/fail/integers/i64/max_fail.leo new file mode 100644 index 0000000000..3e6603e4be --- /dev/null +++ b/asg/tests/fail/integers/i64/max_fail.leo @@ -0,0 +1,3 @@ +function main() { + let a: i64 = 9223372036854775808; +} \ No newline at end of file diff --git a/asg/tests/fail/integers/i64/min_fail.leo b/asg/tests/fail/integers/i64/min_fail.leo new file mode 100644 index 0000000000..11e43646b0 --- /dev/null +++ b/asg/tests/fail/integers/i64/min_fail.leo @@ -0,0 +1,3 @@ +function main() { + let a: i64 = -9223372036854775809; +} \ No newline at end of file diff --git a/asg/tests/fail/integers/i64/mod.rs b/asg/tests/fail/integers/i64/mod.rs new file mode 100644 index 0000000000..6d1aff51ea --- /dev/null +++ b/asg/tests/fail/integers/i64/mod.rs @@ -0,0 +1,50 @@ +// 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 . + +// 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 . + +use super::IntegerTester; + +test_int!(TestI64); + +#[test] +fn test_i64_min_fail() { + TestI64::test_min_fail(); +} + +#[test] +fn test_i64_max_fail() { + TestI64::test_max_fail(); +} + +// #[test] +// fn test_i64_neg_max_fail() { +// TestI64::test_negate_min_fail(); +// } diff --git a/asg/tests/fail/integers/i64/negate_min.leo b/asg/tests/fail/integers/i64/negate_min.leo new file mode 100644 index 0000000000..4dd27778d0 --- /dev/null +++ b/asg/tests/fail/integers/i64/negate_min.leo @@ -0,0 +1,4 @@ +function main() { + let a: i64 = -9223372036854775808; + let b = -a; +} \ No newline at end of file diff --git a/asg/tests/fail/integers/i8/max_fail.leo b/asg/tests/fail/integers/i8/max_fail.leo new file mode 100644 index 0000000000..4892505915 --- /dev/null +++ b/asg/tests/fail/integers/i8/max_fail.leo @@ -0,0 +1,3 @@ +function main() { + let a: i8 = 128; +} \ No newline at end of file diff --git a/asg/tests/fail/integers/i8/min_fail.leo b/asg/tests/fail/integers/i8/min_fail.leo new file mode 100644 index 0000000000..051468ea70 --- /dev/null +++ b/asg/tests/fail/integers/i8/min_fail.leo @@ -0,0 +1,3 @@ +function main() { + let a: i8 = -129; +} \ No newline at end of file diff --git a/asg/tests/fail/integers/i8/mod.rs b/asg/tests/fail/integers/i8/mod.rs new file mode 100644 index 0000000000..c4820fcea5 --- /dev/null +++ b/asg/tests/fail/integers/i8/mod.rs @@ -0,0 +1,50 @@ +// 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 . + +// 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 . + +use super::IntegerTester; + +test_int!(TestI8); + +#[test] +fn test_i8_min_fail() { + TestI8::test_min_fail(); +} + +#[test] +fn test_i8_max_fail() { + TestI8::test_max_fail(); +} + +// #[test] +// fn test_i8_neg_max_fail() { +// TestI8::test_negate_min_fail(); +// } diff --git a/asg/tests/fail/integers/i8/negate_min.leo b/asg/tests/fail/integers/i8/negate_min.leo new file mode 100644 index 0000000000..3959da615e --- /dev/null +++ b/asg/tests/fail/integers/i8/negate_min.leo @@ -0,0 +1,4 @@ +function main() { + let a = -128i8; + let b = -a; +} \ No newline at end of file diff --git a/asg/tests/fail/integers/int_macro.rs b/asg/tests/fail/integers/int_macro.rs new file mode 100644 index 0000000000..697a18998d --- /dev/null +++ b/asg/tests/fail/integers/int_macro.rs @@ -0,0 +1,57 @@ +// 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 . + +// 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 . + +macro_rules! test_int { + ($name: ident) => { + pub struct $name {} + + // we are not doing constant folding here, so asg doesnt catch this + // impl $name { + // fn test_negate_min_fail() { + // let program_string = include_str!("negate_min.leo"); + // crate::load_asg(program_string).err().unwrap(); + // } + // } + + impl super::IntegerTester for $name { + fn test_min_fail() { + let program_string = include_str!("min_fail.leo"); + crate::load_asg(program_string).err().unwrap(); + } + + fn test_max_fail() { + let program_string = include_str!("max_fail.leo"); + crate::load_asg(program_string).err().unwrap(); + } + } + }; +} diff --git a/asg/tests/fail/integers/integer_tester.rs b/asg/tests/fail/integers/integer_tester.rs new file mode 100644 index 0000000000..0c30b88dd1 --- /dev/null +++ b/asg/tests/fail/integers/integer_tester.rs @@ -0,0 +1,39 @@ +// 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 . + +// 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 . + +pub trait IntegerTester { + /// Tests defining the smallest value - 1 + fn test_min_fail(); + + /// Tests defining the largest value + 1 + fn test_max_fail(); +} diff --git a/asg/tests/fail/integers/mod.rs b/asg/tests/fail/integers/mod.rs new file mode 100644 index 0000000000..d9fc896497 --- /dev/null +++ b/asg/tests/fail/integers/mod.rs @@ -0,0 +1,53 @@ +// 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 . + +// 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 . + +#[macro_use] +pub mod int_macro; + +#[macro_use] +pub mod uint_macro; + +pub mod integer_tester; +pub use self::integer_tester::*; + +// must be below macro definitions! +pub mod u128; +pub mod u16; +pub mod u32; +pub mod u64; +pub mod u8; + +pub mod i128; +pub mod i16; +pub mod i32; +pub mod i64; +pub mod i8; diff --git a/asg/tests/fail/integers/u128/max_fail.leo b/asg/tests/fail/integers/u128/max_fail.leo new file mode 100644 index 0000000000..40cdf7d2bb --- /dev/null +++ b/asg/tests/fail/integers/u128/max_fail.leo @@ -0,0 +1,3 @@ +function main() { + let a: u128 = 340282366920938463463374607431768211456; +} \ No newline at end of file diff --git a/asg/tests/fail/integers/u128/min_fail.leo b/asg/tests/fail/integers/u128/min_fail.leo new file mode 100644 index 0000000000..df2390c576 --- /dev/null +++ b/asg/tests/fail/integers/u128/min_fail.leo @@ -0,0 +1,3 @@ +function main() { + let a: u128 = -1; +} \ No newline at end of file diff --git a/asg/tests/fail/integers/u128/mod.rs b/asg/tests/fail/integers/u128/mod.rs new file mode 100644 index 0000000000..45785327f2 --- /dev/null +++ b/asg/tests/fail/integers/u128/mod.rs @@ -0,0 +1,45 @@ +// 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 . + +// 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 . + +use super::IntegerTester; + +test_uint!(TestU128); + +#[test] +fn test_u128_min_fail() { + TestU128::test_min_fail(); +} + +#[test] +fn test_u128_max_fail() { + TestU128::test_max_fail(); +} diff --git a/asg/tests/fail/integers/u16/max_fail.leo b/asg/tests/fail/integers/u16/max_fail.leo new file mode 100644 index 0000000000..68ff0481e0 --- /dev/null +++ b/asg/tests/fail/integers/u16/max_fail.leo @@ -0,0 +1,3 @@ +function main() { + let a: u16 = 65536; +} \ No newline at end of file diff --git a/asg/tests/fail/integers/u16/min_fail.leo b/asg/tests/fail/integers/u16/min_fail.leo new file mode 100644 index 0000000000..99b7310362 --- /dev/null +++ b/asg/tests/fail/integers/u16/min_fail.leo @@ -0,0 +1,3 @@ +function main() { + let a: u16 = -1; +} \ No newline at end of file diff --git a/asg/tests/fail/integers/u16/mod.rs b/asg/tests/fail/integers/u16/mod.rs new file mode 100644 index 0000000000..10f8c85612 --- /dev/null +++ b/asg/tests/fail/integers/u16/mod.rs @@ -0,0 +1,45 @@ +// 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 . + +// 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 . + +use super::IntegerTester; + +test_uint!(TestU16); + +#[test] +fn test_u16_min_fail() { + TestU16::test_min_fail(); +} + +#[test] +fn test_u16_max_fail() { + TestU16::test_max_fail(); +} diff --git a/asg/tests/fail/integers/u32/max_fail.leo b/asg/tests/fail/integers/u32/max_fail.leo new file mode 100644 index 0000000000..96c7e01657 --- /dev/null +++ b/asg/tests/fail/integers/u32/max_fail.leo @@ -0,0 +1,3 @@ +function main() { + let a: u32 = 4294967296; +} \ No newline at end of file diff --git a/asg/tests/fail/integers/u32/min_fail.leo b/asg/tests/fail/integers/u32/min_fail.leo new file mode 100644 index 0000000000..a8d41c475a --- /dev/null +++ b/asg/tests/fail/integers/u32/min_fail.leo @@ -0,0 +1,3 @@ +function main() { + let a: u32 = -1; +} \ No newline at end of file diff --git a/asg/tests/fail/integers/u32/mod.rs b/asg/tests/fail/integers/u32/mod.rs new file mode 100644 index 0000000000..65b17b801d --- /dev/null +++ b/asg/tests/fail/integers/u32/mod.rs @@ -0,0 +1,45 @@ +// 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 . + +// 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 . + +use super::IntegerTester; + +test_uint!(TestU32); + +#[test] +fn test_u32_min_fail() { + TestU32::test_min_fail(); +} + +#[test] +fn test_u32_max_fail() { + TestU32::test_max_fail(); +} diff --git a/asg/tests/fail/integers/u64/max_fail.leo b/asg/tests/fail/integers/u64/max_fail.leo new file mode 100644 index 0000000000..0ca3f13895 --- /dev/null +++ b/asg/tests/fail/integers/u64/max_fail.leo @@ -0,0 +1,3 @@ +function main() { + let a: u64 = 18446744073709551616; +} \ No newline at end of file diff --git a/asg/tests/fail/integers/u64/min_fail.leo b/asg/tests/fail/integers/u64/min_fail.leo new file mode 100644 index 0000000000..81b90cc74a --- /dev/null +++ b/asg/tests/fail/integers/u64/min_fail.leo @@ -0,0 +1,3 @@ +function main() { + let a: u64 = -1; +} \ No newline at end of file diff --git a/asg/tests/fail/integers/u64/mod.rs b/asg/tests/fail/integers/u64/mod.rs new file mode 100644 index 0000000000..416ebdc3b6 --- /dev/null +++ b/asg/tests/fail/integers/u64/mod.rs @@ -0,0 +1,45 @@ +// 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 . + +// 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 . + +use super::IntegerTester; + +test_uint!(TestU64); + +#[test] +fn test_u64_min_fail() { + TestU64::test_min_fail(); +} + +#[test] +fn test_u64_max_fail() { + TestU64::test_max_fail(); +} diff --git a/asg/tests/fail/integers/u8/max_fail.leo b/asg/tests/fail/integers/u8/max_fail.leo new file mode 100644 index 0000000000..f2b870096d --- /dev/null +++ b/asg/tests/fail/integers/u8/max_fail.leo @@ -0,0 +1,3 @@ +function main() { + let a: u8 = 256; +} \ No newline at end of file diff --git a/asg/tests/fail/integers/u8/min_fail.leo b/asg/tests/fail/integers/u8/min_fail.leo new file mode 100644 index 0000000000..7b91dc6e1a --- /dev/null +++ b/asg/tests/fail/integers/u8/min_fail.leo @@ -0,0 +1,3 @@ +function main() { + let a: u8 = -1; +} \ No newline at end of file diff --git a/asg/tests/fail/integers/u8/mod.rs b/asg/tests/fail/integers/u8/mod.rs new file mode 100644 index 0000000000..3eb6ca944c --- /dev/null +++ b/asg/tests/fail/integers/u8/mod.rs @@ -0,0 +1,45 @@ +// 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 . + +// 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 . + +use super::IntegerTester; + +test_uint!(TestU8); + +#[test] +fn test_u8_min_fail() { + TestU8::test_min_fail(); +} + +#[test] +fn test_u8_max_fail() { + TestU8::test_max_fail(); +} diff --git a/asg/tests/fail/integers/uint_macro.rs b/asg/tests/fail/integers/uint_macro.rs new file mode 100644 index 0000000000..ac81632566 --- /dev/null +++ b/asg/tests/fail/integers/uint_macro.rs @@ -0,0 +1,49 @@ +// 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 . + +// 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 . + +macro_rules! test_uint { + ($name: ident) => { + pub struct $name {} + + impl super::IntegerTester for $name { + fn test_min_fail() { + let program_string = include_str!("min_fail.leo"); + crate::load_asg(program_string).err().unwrap(); + } + + fn test_max_fail() { + let program_string = include_str!("max_fail.leo"); + crate::load_asg(program_string).err().unwrap(); + } + } + }; +} diff --git a/asg/tests/fail/mod.rs b/asg/tests/fail/mod.rs new file mode 100644 index 0000000000..718731f2c3 --- /dev/null +++ b/asg/tests/fail/mod.rs @@ -0,0 +1,47 @@ +// 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 . + +// 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 . + +pub mod address; +pub mod array; +pub mod boolean; +pub mod circuits; +pub mod console; +pub mod core; +pub mod definition; +pub mod field; +pub mod function; +// pub mod group; // we dont do context-specific type checking for groups +pub mod import; +pub mod integers; +pub mod mutability; +pub mod statements; +pub mod tuples; diff --git a/asg/tests/fail/mutability/array.leo b/asg/tests/fail/mutability/array.leo new file mode 100644 index 0000000000..1d51c15271 --- /dev/null +++ b/asg/tests/fail/mutability/array.leo @@ -0,0 +1,5 @@ +// Arrays are immutable by default. +function main() { + let a = [1u32]; + a[0] = 0; +} \ No newline at end of file diff --git a/asg/tests/fail/mutability/circuit.leo b/asg/tests/fail/mutability/circuit.leo new file mode 100644 index 0000000000..be1c568836 --- /dev/null +++ b/asg/tests/fail/mutability/circuit.leo @@ -0,0 +1,9 @@ +// Circuits are immutable by default. +circuit Foo { + x: u32 +} + +function main() { + let a = Foo { x: 1 }; + a.x = 0; +} \ No newline at end of file diff --git a/asg/tests/fail/mutability/circuit_function_mut.leo b/asg/tests/fail/mutability/circuit_function_mut.leo new file mode 100644 index 0000000000..eba1d02c0e --- /dev/null +++ b/asg/tests/fail/mutability/circuit_function_mut.leo @@ -0,0 +1,9 @@ +// Adding the `mut` keyword makes a circuit variable mutable. +circuit Foo { + function bar() {} +} + +function main() { + let mut a = Foo { x: 1 }; + a.bar = 0; +} \ No newline at end of file diff --git a/asg/tests/fail/mutability/circuit_static_function_mut.leo b/asg/tests/fail/mutability/circuit_static_function_mut.leo new file mode 100644 index 0000000000..eba1d02c0e --- /dev/null +++ b/asg/tests/fail/mutability/circuit_static_function_mut.leo @@ -0,0 +1,9 @@ +// Adding the `mut` keyword makes a circuit variable mutable. +circuit Foo { + function bar() {} +} + +function main() { + let mut a = Foo { x: 1 }; + a.bar = 0; +} \ No newline at end of file diff --git a/asg/tests/fail/mutability/const.leo b/asg/tests/fail/mutability/const.leo new file mode 100644 index 0000000000..44f9279085 --- /dev/null +++ b/asg/tests/fail/mutability/const.leo @@ -0,0 +1,5 @@ +// Constant variables are immutable by default. +function main() { + const a = 1u32; + a = 0; +} \ No newline at end of file diff --git a/asg/tests/fail/mutability/const_mut.leo b/asg/tests/fail/mutability/const_mut.leo new file mode 100644 index 0000000000..ef194ae178 --- /dev/null +++ b/asg/tests/fail/mutability/const_mut.leo @@ -0,0 +1,4 @@ +// Adding the `mut` keyword to a constant variable is illegal +function main() { + const mut a = 1u32; +} \ No newline at end of file diff --git a/asg/tests/fail/mutability/function_input.leo b/asg/tests/fail/mutability/function_input.leo new file mode 100644 index 0000000000..1ef3ce1f02 --- /dev/null +++ b/asg/tests/fail/mutability/function_input.leo @@ -0,0 +1,4 @@ +// Function input are immutable by default. +function main(a: bool) { + a = false; +} \ No newline at end of file diff --git a/asg/tests/fail/mutability/let.leo b/asg/tests/fail/mutability/let.leo new file mode 100644 index 0000000000..477e6b35f5 --- /dev/null +++ b/asg/tests/fail/mutability/let.leo @@ -0,0 +1,5 @@ +// Variables are immutable by default. +function main() { + let a = 1u32; + a = 0; +} \ No newline at end of file diff --git a/asg/tests/fail/mutability/mod.rs b/asg/tests/fail/mutability/mod.rs new file mode 100644 index 0000000000..642369feb6 --- /dev/null +++ b/asg/tests/fail/mutability/mod.rs @@ -0,0 +1,81 @@ +// 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 . + +// 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 . + +use crate::load_asg; + +#[test] +fn test_let() { + let program_string = include_str!("let.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_const_fail() { + let program_string = include_str!("const.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_const_mut_fail() { + let program_string = include_str!("const_mut.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_array() { + let program_string = include_str!("array.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_circuit() { + let program_string = include_str!("circuit.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_circuit_function_mut() { + let program_string = include_str!("circuit_function_mut.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_circuit_static_function_mut() { + let program_string = include_str!("circuit_static_function_mut.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_function_input() { + let program_string = include_str!("function_input.leo"); + load_asg(program_string).err().unwrap(); +} diff --git a/asg/tests/fail/statements/mod.rs b/asg/tests/fail/statements/mod.rs new file mode 100644 index 0000000000..99ad1332df --- /dev/null +++ b/asg/tests/fail/statements/mod.rs @@ -0,0 +1,39 @@ +// 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 . + +// 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 . + +use crate::load_asg; + +#[test] +fn test_num_returns_fail() { + let program_string = include_str!("num_returns_fail.leo"); + load_asg(program_string).err().unwrap(); +} diff --git a/asg/tests/fail/statements/num_returns_fail.leo b/asg/tests/fail/statements/num_returns_fail.leo new file mode 100644 index 0000000000..14b2fe6ad0 --- /dev/null +++ b/asg/tests/fail/statements/num_returns_fail.leo @@ -0,0 +1,3 @@ +function main() -> (bool, bool) { + return true +} \ No newline at end of file diff --git a/asg/tests/fail/tuples/mod.rs b/asg/tests/fail/tuples/mod.rs new file mode 100644 index 0000000000..e946846b69 --- /dev/null +++ b/asg/tests/fail/tuples/mod.rs @@ -0,0 +1,31 @@ +// 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 . + +// 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 . diff --git a/asg/tests/mod.rs b/asg/tests/mod.rs new file mode 100644 index 0000000000..631ade6e5b --- /dev/null +++ b/asg/tests/mod.rs @@ -0,0 +1,33 @@ +// 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 . + +use leo_asg::*; + +mod fail; +mod pass; + +fn load_asg(content: &str) -> Result { + leo_asg::load_asg(content, &mut NullImportResolver) +} + +fn load_asg_imports(content: &str, imports: &mut T) -> Result { + leo_asg::load_asg(content, imports) +} + +fn mocked_resolver() -> MockedImportResolver { + let packages = indexmap::IndexMap::new(); + MockedImportResolver { packages } +} diff --git a/asg/tests/pass/address/console_assert_pass.leo b/asg/tests/pass/address/console_assert_pass.leo new file mode 100644 index 0000000000..60ea4a79cd --- /dev/null +++ b/asg/tests/pass/address/console_assert_pass.leo @@ -0,0 +1,6 @@ +function main() { + let address_1 = address(aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8); + let address_2 = address(aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8); + + console.assert(address_1 == address_2); +} \ No newline at end of file diff --git a/asg/tests/pass/address/equal.leo b/asg/tests/pass/address/equal.leo new file mode 100644 index 0000000000..9012a8c49d --- /dev/null +++ b/asg/tests/pass/address/equal.leo @@ -0,0 +1,3 @@ +function main(a: address, b: address, c: bool) { + console.assert(a == b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/address/implicit_invalid.leo b/asg/tests/pass/address/implicit_invalid.leo new file mode 100644 index 0000000000..6f8eba5114 --- /dev/null +++ b/asg/tests/pass/address/implicit_invalid.leo @@ -0,0 +1,3 @@ +function main() { + let public_key_string: address = zleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8; +} \ No newline at end of file diff --git a/asg/tests/pass/address/implicit_valid.leo b/asg/tests/pass/address/implicit_valid.leo new file mode 100644 index 0000000000..df6ebf497d --- /dev/null +++ b/asg/tests/pass/address/implicit_valid.leo @@ -0,0 +1,3 @@ +function main() { + let public_key_string: address = aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8; +} \ No newline at end of file diff --git a/asg/tests/pass/address/input.leo b/asg/tests/pass/address/input.leo new file mode 100644 index 0000000000..795deac98b --- /dev/null +++ b/asg/tests/pass/address/input.leo @@ -0,0 +1,5 @@ +function main(owner: address) { + let sender = address(aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8); + + console.assert(owner == sender); +} \ No newline at end of file diff --git a/asg/tests/pass/address/mod.rs b/asg/tests/pass/address/mod.rs new file mode 100644 index 0000000000..1237a2fd06 --- /dev/null +++ b/asg/tests/pass/address/mod.rs @@ -0,0 +1,64 @@ +// 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 . + +// 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 . + +use crate::load_asg; + +#[test] +fn test_valid() { + let program_string = include_str!("valid.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_implicit_valid() { + let program_string = include_str!("implicit_valid.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_console_assert_pass() { + let program_string = include_str!("console_assert_pass.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_ternary() { + let program_string = include_str!("ternary.leo"); + + load_asg(program_string).unwrap(); +} + +#[test] +fn test_equal() { + let program_string = include_str!("equal.leo"); + load_asg(program_string).unwrap(); +} diff --git a/asg/tests/pass/address/ternary.leo b/asg/tests/pass/address/ternary.leo new file mode 100644 index 0000000000..29ecccb918 --- /dev/null +++ b/asg/tests/pass/address/ternary.leo @@ -0,0 +1,8 @@ +function main(s: bool, c: address) { + let a = address(aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8); + let b = address(aleo18qgam03qe483tdrcc3fkqwpp38ehff4a2xma6lu7hams6lfpgcpq3dq05r); + + let r = if s? a: b; + + console.assert(r == c); +} \ No newline at end of file diff --git a/asg/tests/pass/address/valid.leo b/asg/tests/pass/address/valid.leo new file mode 100644 index 0000000000..f06aefdaa6 --- /dev/null +++ b/asg/tests/pass/address/valid.leo @@ -0,0 +1,3 @@ +function main() { + let public_key_string = address(aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8); +} \ No newline at end of file diff --git a/asg/tests/pass/array/index_u8.leo b/asg/tests/pass/array/index_u8.leo new file mode 100644 index 0000000000..7ad1c6a9ea --- /dev/null +++ b/asg/tests/pass/array/index_u8.leo @@ -0,0 +1,5 @@ +function main() { + let x = 0u8; + let a = [0u8; 4]; + console.assert(a[x] == 0); +} diff --git a/asg/tests/pass/array/initializer.leo b/asg/tests/pass/array/initializer.leo new file mode 100644 index 0000000000..51ac19f68f --- /dev/null +++ b/asg/tests/pass/array/initializer.leo @@ -0,0 +1,3 @@ +function main(a: [u8; 3]) { + console.assert(a == [1u8; 3]); +} \ No newline at end of file diff --git a/asg/tests/pass/array/initializer_input.leo b/asg/tests/pass/array/initializer_input.leo new file mode 100644 index 0000000000..4b886159dc --- /dev/null +++ b/asg/tests/pass/array/initializer_input.leo @@ -0,0 +1,3 @@ +function main(a: [u8; (3, 2)]) { + console.assert(a == [0u8; (3, 2)]); +} \ No newline at end of file diff --git a/asg/tests/pass/array/inline.leo b/asg/tests/pass/array/inline.leo new file mode 100644 index 0000000000..8c5c98ae50 --- /dev/null +++ b/asg/tests/pass/array/inline.leo @@ -0,0 +1,3 @@ +function main(a: [u8; 3]) { + console.assert(a == [1u8, 1u8, 1u8]); +} \ No newline at end of file diff --git a/asg/tests/pass/array/input_nested_3x2.leo b/asg/tests/pass/array/input_nested_3x2.leo new file mode 100644 index 0000000000..b7e59a5dc0 --- /dev/null +++ b/asg/tests/pass/array/input_nested_3x2.leo @@ -0,0 +1,3 @@ +function main(a: [u8; (3, 2)]) { + console.assert(a == [[0u8; 2]; 3]); +} diff --git a/asg/tests/pass/array/input_tuple_3x2.leo b/asg/tests/pass/array/input_tuple_3x2.leo new file mode 100644 index 0000000000..4c3c001f41 --- /dev/null +++ b/asg/tests/pass/array/input_tuple_3x2.leo @@ -0,0 +1,3 @@ +function main(a: [u8; (3, 2)]) { + console.assert(a == [0u8; (3, 2)]); +} diff --git a/asg/tests/pass/array/mod.rs b/asg/tests/pass/array/mod.rs new file mode 100644 index 0000000000..563d4bad61 --- /dev/null +++ b/asg/tests/pass/array/mod.rs @@ -0,0 +1,217 @@ +// 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 . + +// 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 . + +use crate::load_asg; + +// Registers + +#[test] +fn test_registers() { + let program_string = include_str!("registers.leo"); + load_asg(program_string).unwrap(); +} + +// Expressions + +#[test] +fn test_inline() { + let program_string = include_str!("inline.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_initializer() { + let program_string = include_str!("initializer.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_initializer_input() { + let program_string = include_str!("initializer_input.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_input_nested_3x2() { + let program_string = include_str!("input_nested_3x2.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_input_tuple_3x2() { + let program_string = include_str!("input_tuple_3x2.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_multi_initializer() { + let program_string = include_str!("multi_initializer.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_nested_3x2_value() { + let program_string = include_str!("nested_3x2_value.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_tuple_3x2_value() { + let program_string = include_str!("tuple_3x2_value.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_spread() { + let program_string = include_str!("spread.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_slice() { + let program_string = include_str!("slice.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_index_u8() { + let program_string = include_str!("index_u8.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_slice_i8() { + let program_string = include_str!("slice_i8.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_slice_lower() { + let program_string = include_str!("slice_lower.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_type_nested_value_nested_3x2() { + let program_string = include_str!("type_nested_value_nested_3x2.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_type_nested_value_nested_4x3x2() { + let program_string = include_str!("type_nested_value_nested_4x3x2.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_type_nested_value_tuple_3x2() { + let program_string = include_str!("type_nested_value_tuple_3x2.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_type_nested_value_tuple_4x3x2() { + let program_string = include_str!("type_nested_value_tuple_4x3x2.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_type_tuple_value_nested_3x2() { + let program_string = include_str!("type_tuple_value_nested_3x2.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_type_tuple_value_nested_4x3x2() { + let program_string = include_str!("type_tuple_value_nested_4x3x2.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_type_tuple_value_tuple_3x2() { + let program_string = include_str!("type_tuple_value_tuple_3x2.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_type_tuple_value_tuple_4x3x2() { + let program_string = include_str!("type_tuple_value_tuple_4x3x2.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_input_type_nested_value_nested_3x2() { + let program_string = include_str!("type_input_3x2.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_input_type_nested_value_nested_4x3x2() { + let program_string = include_str!("type_input_4x3x2.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_input_type_nested_value_tuple_3x2() { + let program_string = include_str!("type_input_3x2.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_input_type_nested_value_tuple_4x3x2() { + let program_string = include_str!("type_input_4x3x2.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_input_type_tuple_value_nested_3x2() { + let program_string = include_str!("type_input_3x2.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_input_type_tuple_value_nested_4x3x2() { + let program_string = include_str!("type_input_4x3x2.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_input_type_tuple_value_tuple_3x2() { + let program_string = include_str!("type_input_3x2.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_input_type_tuple_value_tuple_4x3x2() { + let program_string = include_str!("type_input_4x3x2.leo"); + load_asg(program_string).unwrap(); +} diff --git a/asg/tests/pass/array/multi_initializer.leo b/asg/tests/pass/array/multi_initializer.leo new file mode 100644 index 0000000000..6133542ef0 --- /dev/null +++ b/asg/tests/pass/array/multi_initializer.leo @@ -0,0 +1,7 @@ +function main() { + const a: [u8; (2, 2, 2)] = [1u8; (2, 2, 2)]; + + const b: [u8; (2, 2, 2)] = [[[1u8; 2]; 2]; 2]; + + console.assert(a == b); +} \ No newline at end of file diff --git a/asg/tests/pass/array/nested_3x2_value.leo b/asg/tests/pass/array/nested_3x2_value.leo new file mode 100644 index 0000000000..c5f64c997e --- /dev/null +++ b/asg/tests/pass/array/nested_3x2_value.leo @@ -0,0 +1,8 @@ +// Multidimensional array syntax in leo +function main() { + const a = [[0u32, 0u32], [0u32, 0u32], [0u32, 0u32]]; // inline + + const b: [u32; (3, 2)] = [[0; 2]; 3]; // initializer + + console.assert(a == b); +} \ No newline at end of file diff --git a/asg/tests/pass/array/registers.leo b/asg/tests/pass/array/registers.leo new file mode 100644 index 0000000000..fb8980868e --- /dev/null +++ b/asg/tests/pass/array/registers.leo @@ -0,0 +1,3 @@ +function main(input) -> [u8; 3] { + return input.registers.r +} \ No newline at end of file diff --git a/asg/tests/pass/array/slice.leo b/asg/tests/pass/array/slice.leo new file mode 100644 index 0000000000..296f5bd050 --- /dev/null +++ b/asg/tests/pass/array/slice.leo @@ -0,0 +1,6 @@ +// `{from}..{to}` copies the elements of one array into another exclusively +function main(a: [u8; 3]) { + let b = [1u8; 4]; + + console.assert(a == b[0..3]); +} diff --git a/asg/tests/pass/array/slice_i8.leo b/asg/tests/pass/array/slice_i8.leo new file mode 100644 index 0000000000..bc3d884cc6 --- /dev/null +++ b/asg/tests/pass/array/slice_i8.leo @@ -0,0 +1,6 @@ +// `{from}..{to}` copies the elements of one array into another exclusively +function main(a: [u8; 3]) { + let b = [1u8; 4]; + + console.assert(a == b[0u8..3i8]); +} diff --git a/asg/tests/pass/array/slice_lower.leo b/asg/tests/pass/array/slice_lower.leo new file mode 100644 index 0000000000..dd669830ea --- /dev/null +++ b/asg/tests/pass/array/slice_lower.leo @@ -0,0 +1,8 @@ +function main() { + let arr: [u32; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; + let expected: [u32; 2] = [0, 1]; + + let actual = arr[..2]; // Should produce [0, 1] + + console.assert(expected == actual); +} \ No newline at end of file diff --git a/asg/tests/pass/array/spread.leo b/asg/tests/pass/array/spread.leo new file mode 100644 index 0000000000..962e92c923 --- /dev/null +++ b/asg/tests/pass/array/spread.leo @@ -0,0 +1,7 @@ +// A spread operator `...` copies the elements of one array into another +function main(a: [u8; 3]) { + let b = [1u8, 1u8]; + let c = [1u8, ...b]; + + console.assert(a == c); +} \ No newline at end of file diff --git a/asg/tests/pass/array/tuple_3x2_value.leo b/asg/tests/pass/array/tuple_3x2_value.leo new file mode 100644 index 0000000000..b6659539d5 --- /dev/null +++ b/asg/tests/pass/array/tuple_3x2_value.leo @@ -0,0 +1,8 @@ +// Multidimensional array syntax in leo +function main() { + const a = [[0u32, 0u32], [0u32, 0u32], [0u32, 0u32]]; // inline + + const b: [u32; (3, 2)] = [0; (3, 2)]; // initializer + + console.assert(a == b); +} \ No newline at end of file diff --git a/asg/tests/pass/array/type_input_3x2.leo b/asg/tests/pass/array/type_input_3x2.leo new file mode 100644 index 0000000000..ea60a0cc24 --- /dev/null +++ b/asg/tests/pass/array/type_input_3x2.leo @@ -0,0 +1,5 @@ +function main(a: [[u8; 2]; 3]) { + const b = [[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]]; // inline + + console.assert(a == b); +} \ No newline at end of file diff --git a/asg/tests/pass/array/type_input_4x3x2.leo b/asg/tests/pass/array/type_input_4x3x2.leo new file mode 100644 index 0000000000..2d9c4cff22 --- /dev/null +++ b/asg/tests/pass/array/type_input_4x3x2.leo @@ -0,0 +1,8 @@ +function main(a: [[[u8; 2]; 3]; 4]) { + const b = [[[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]], + [[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]], + [[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]], + [[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]]]; // inline + + console.assert(a == b); +} \ No newline at end of file diff --git a/asg/tests/pass/array/type_nested_value_nested_3x2.leo b/asg/tests/pass/array/type_nested_value_nested_3x2.leo new file mode 100644 index 0000000000..bcf5bae674 --- /dev/null +++ b/asg/tests/pass/array/type_nested_value_nested_3x2.leo @@ -0,0 +1,7 @@ +function main() { + const a = [[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]]; // inline + + const b: [[u8; 2]; 3] = [[0; 2]; 3]; // initializer + + console.assert(a == b); +} \ No newline at end of file diff --git a/asg/tests/pass/array/type_nested_value_nested_4x3x2.leo b/asg/tests/pass/array/type_nested_value_nested_4x3x2.leo new file mode 100644 index 0000000000..1691fa26c7 --- /dev/null +++ b/asg/tests/pass/array/type_nested_value_nested_4x3x2.leo @@ -0,0 +1,10 @@ +function main() { + const a = [[[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]], + [[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]], + [[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]], + [[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]]]; // inline + + const b: [[[u8; 2]; 3]; 4] = [[[0; 2]; 3]; 4]; // initializer + + console.assert(a == b); +} \ No newline at end of file diff --git a/asg/tests/pass/array/type_nested_value_tuple_3x2.leo b/asg/tests/pass/array/type_nested_value_tuple_3x2.leo new file mode 100644 index 0000000000..5f14084d55 --- /dev/null +++ b/asg/tests/pass/array/type_nested_value_tuple_3x2.leo @@ -0,0 +1,7 @@ +function main() { + const a = [[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]]; // inline + + const b: [[u8; 2]; 3] = [0; (3, 2)]; // initializer + + console.assert(a == b); +} \ No newline at end of file diff --git a/asg/tests/pass/array/type_nested_value_tuple_4x3x2.leo b/asg/tests/pass/array/type_nested_value_tuple_4x3x2.leo new file mode 100644 index 0000000000..88a5143bd2 --- /dev/null +++ b/asg/tests/pass/array/type_nested_value_tuple_4x3x2.leo @@ -0,0 +1,10 @@ +function main() { + const a = [[[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]], + [[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]], + [[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]], + [[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]]]; // inline + + const b: [[[u8; 2]; 3]; 4] = [0; (4, 3, 2)]; // initializer + + console.assert(a == b); +} \ No newline at end of file diff --git a/asg/tests/pass/array/type_tuple_value_nested_3x2.leo b/asg/tests/pass/array/type_tuple_value_nested_3x2.leo new file mode 100644 index 0000000000..81195e03a1 --- /dev/null +++ b/asg/tests/pass/array/type_tuple_value_nested_3x2.leo @@ -0,0 +1,7 @@ +function main() { + const a = [[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]]; // inline + + const b: [u8; (3, 2)] = [[0; 2]; 3]; // initializer + + console.assert(a == b); +} \ No newline at end of file diff --git a/asg/tests/pass/array/type_tuple_value_nested_4x3x2.leo b/asg/tests/pass/array/type_tuple_value_nested_4x3x2.leo new file mode 100644 index 0000000000..322a6f7601 --- /dev/null +++ b/asg/tests/pass/array/type_tuple_value_nested_4x3x2.leo @@ -0,0 +1,10 @@ +function main() { + const a = [[[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]], + [[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]], + [[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]], + [[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]]]; // inline + + const b: [u8; (4, 3, 2)] = [[[0; 2]; 3]; 4]; // initializer + + console.assert(a == b); +} \ No newline at end of file diff --git a/asg/tests/pass/array/type_tuple_value_tuple_3x2.leo b/asg/tests/pass/array/type_tuple_value_tuple_3x2.leo new file mode 100644 index 0000000000..d451a9c1a8 --- /dev/null +++ b/asg/tests/pass/array/type_tuple_value_tuple_3x2.leo @@ -0,0 +1,7 @@ +function main() { + const a = [[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]]; // inline + + const b: [u8; (3, 2)] = [0; (3, 2)]; // initializer + + console.assert(a == b); +} \ No newline at end of file diff --git a/asg/tests/pass/array/type_tuple_value_tuple_4x3x2.leo b/asg/tests/pass/array/type_tuple_value_tuple_4x3x2.leo new file mode 100644 index 0000000000..1205b1dc9c --- /dev/null +++ b/asg/tests/pass/array/type_tuple_value_tuple_4x3x2.leo @@ -0,0 +1,10 @@ +function main() { + const a = [[[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]], + [[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]], + [[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]], + [[0u8, 0u8], [0u8, 0u8], [0u8, 0u8]]]; // inline + + const b: [u8; (4, 3, 2)] = [0; (4, 3, 2)]; // initializer + + console.assert(a == b); +} \ No newline at end of file diff --git a/asg/tests/pass/boolean/all.leo b/asg/tests/pass/boolean/all.leo new file mode 100644 index 0000000000..64fe8a795a --- /dev/null +++ b/asg/tests/pass/boolean/all.leo @@ -0,0 +1,8 @@ +// !(true && (false || true)) +function main() { + const a = true; + const b = false || a; + const c = !(true && b); + + console.assert(c == false); +} \ No newline at end of file diff --git a/asg/tests/pass/boolean/assert_eq_input.leo b/asg/tests/pass/boolean/assert_eq_input.leo new file mode 100644 index 0000000000..8a796e5bbd --- /dev/null +++ b/asg/tests/pass/boolean/assert_eq_input.leo @@ -0,0 +1,3 @@ +function main(a: bool, b: bool) { + console.assert(a == b); +} \ No newline at end of file diff --git a/asg/tests/pass/boolean/false_and_false.leo b/asg/tests/pass/boolean/false_and_false.leo new file mode 100644 index 0000000000..70e4b0797b --- /dev/null +++ b/asg/tests/pass/boolean/false_and_false.leo @@ -0,0 +1,5 @@ +function main() { + let a = false && false; + + console.assert(a == false); +} \ No newline at end of file diff --git a/asg/tests/pass/boolean/false_or_false.leo b/asg/tests/pass/boolean/false_or_false.leo new file mode 100644 index 0000000000..4ae820254e --- /dev/null +++ b/asg/tests/pass/boolean/false_or_false.leo @@ -0,0 +1,5 @@ +function main() { + let a = false || false; + + console.assert(a == false); +} \ No newline at end of file diff --git a/asg/tests/pass/boolean/mod.rs b/asg/tests/pass/boolean/mod.rs new file mode 100644 index 0000000000..e23749836b --- /dev/null +++ b/asg/tests/pass/boolean/mod.rs @@ -0,0 +1,113 @@ +// 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 . + +// 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 . + +use crate::load_asg; + +#[test] +fn test_input_pass() { + let program_string = include_str!("assert_eq_input.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_registers() { + let program_string = include_str!("output_register.leo"); + load_asg(program_string).unwrap(); +} + +// Boolean not ! + +#[test] +fn test_not_true() { + let program_string = include_str!("not_true.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_not_false() { + let program_string = include_str!("not_false.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_not_mutable() { + let program_string = include_str!("not_mutable.leo"); + load_asg(program_string).unwrap(); +} + +// Boolean or || + +#[test] +fn test_true_or_true() { + let program_string = include_str!("true_or_true.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_true_or_false() { + let program_string = include_str!("true_or_false.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_false_or_false() { + let program_string = include_str!("false_or_false.leo"); + load_asg(program_string).unwrap(); +} + +// Boolean and && + +#[test] +fn test_true_and_true() { + let program_string = include_str!("true_and_true.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_true_and_false() { + let program_string = include_str!("true_and_false.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_false_and_false() { + let program_string = include_str!("false_and_false.leo"); + load_asg(program_string).unwrap(); +} + +// All + +#[test] +fn test_all() { + let program_string = include_str!("all.leo"); + load_asg(program_string).unwrap(); +} diff --git a/asg/tests/pass/boolean/not_false.leo b/asg/tests/pass/boolean/not_false.leo new file mode 100644 index 0000000000..796b616871 --- /dev/null +++ b/asg/tests/pass/boolean/not_false.leo @@ -0,0 +1,3 @@ +function main() { + console.assert(!false == true); +} \ No newline at end of file diff --git a/asg/tests/pass/boolean/not_mutable.leo b/asg/tests/pass/boolean/not_mutable.leo new file mode 100644 index 0000000000..91a6e5ff37 --- /dev/null +++ b/asg/tests/pass/boolean/not_mutable.leo @@ -0,0 +1,4 @@ +function main () { + let mut b = false; + let a = !b; +} \ No newline at end of file diff --git a/asg/tests/pass/boolean/not_true.leo b/asg/tests/pass/boolean/not_true.leo new file mode 100644 index 0000000000..8c87dffabb --- /dev/null +++ b/asg/tests/pass/boolean/not_true.leo @@ -0,0 +1,3 @@ +function main() { + console.assert(!true == false); +} \ No newline at end of file diff --git a/asg/tests/pass/boolean/output_register.leo b/asg/tests/pass/boolean/output_register.leo new file mode 100644 index 0000000000..fb01d41dbe --- /dev/null +++ b/asg/tests/pass/boolean/output_register.leo @@ -0,0 +1,3 @@ +function main(input) -> bool { + return input.registers.r +} \ No newline at end of file diff --git a/asg/tests/pass/boolean/true_and_false.leo b/asg/tests/pass/boolean/true_and_false.leo new file mode 100644 index 0000000000..3c7c484603 --- /dev/null +++ b/asg/tests/pass/boolean/true_and_false.leo @@ -0,0 +1,5 @@ +function main() { + let a = true && false; + + console.assert(a == false); +} \ No newline at end of file diff --git a/asg/tests/pass/boolean/true_and_true.leo b/asg/tests/pass/boolean/true_and_true.leo new file mode 100644 index 0000000000..c378e50024 --- /dev/null +++ b/asg/tests/pass/boolean/true_and_true.leo @@ -0,0 +1,5 @@ +function main() { + let a = true && true; + + console.assert(a == true); +} \ No newline at end of file diff --git a/asg/tests/pass/boolean/true_or_false.leo b/asg/tests/pass/boolean/true_or_false.leo new file mode 100644 index 0000000000..d643a96aa1 --- /dev/null +++ b/asg/tests/pass/boolean/true_or_false.leo @@ -0,0 +1,5 @@ +function main() { + let a = true || false; + + console.assert(a == true); +} \ No newline at end of file diff --git a/asg/tests/pass/boolean/true_or_true.leo b/asg/tests/pass/boolean/true_or_true.leo new file mode 100644 index 0000000000..b8eaa91ff1 --- /dev/null +++ b/asg/tests/pass/boolean/true_or_true.leo @@ -0,0 +1,5 @@ +function main() { + let a = true || true; + + console.assert(a == true); +} \ No newline at end of file diff --git a/asg/tests/pass/circuits/define_circuit_inside_circuit_function.leo b/asg/tests/pass/circuits/define_circuit_inside_circuit_function.leo new file mode 100644 index 0000000000..8c25c1e9d9 --- /dev/null +++ b/asg/tests/pass/circuits/define_circuit_inside_circuit_function.leo @@ -0,0 +1,13 @@ +circuit Foo { + a: u32, +} + +circuit Bar { + function bar() { + let f = Foo { a: 0u32 }; + } +} + +function main() { + let b = Bar::bar(); +} \ No newline at end of file diff --git a/asg/tests/pass/circuits/inline.leo b/asg/tests/pass/circuits/inline.leo new file mode 100644 index 0000000000..8e214c729a --- /dev/null +++ b/asg/tests/pass/circuits/inline.leo @@ -0,0 +1,7 @@ +circuit Foo { + x: u32 +} + +function main() { + let a = Foo { x: 1u32 }; +} \ No newline at end of file diff --git a/asg/tests/pass/circuits/member_function.leo b/asg/tests/pass/circuits/member_function.leo new file mode 100644 index 0000000000..3c9aa1aa60 --- /dev/null +++ b/asg/tests/pass/circuits/member_function.leo @@ -0,0 +1,11 @@ +circuit Foo { + function echo(self, x: u32) -> u32 { + return x + } +} + +function main() { + let a = Foo { }; + + console.assert(a.echo(1u32) == 1u32); +} \ No newline at end of file diff --git a/asg/tests/pass/circuits/member_function_nested.leo b/asg/tests/pass/circuits/member_function_nested.leo new file mode 100644 index 0000000000..9e07cc9acf --- /dev/null +++ b/asg/tests/pass/circuits/member_function_nested.leo @@ -0,0 +1,18 @@ +circuit Foo { + x: u32, + + function add_x(self, y: u32) -> u32 { + return self.x + y + } + + function call_add_x(self, y: u32) -> u32 { + return self.add_x(y) + } +} + +function main() { + let a = Foo { x: 1u32 }; + let b = a.add_x(1u32); + + console.assert(b == 2u32); +} diff --git a/asg/tests/pass/circuits/member_static_function.leo b/asg/tests/pass/circuits/member_static_function.leo new file mode 100644 index 0000000000..4bf51190f0 --- /dev/null +++ b/asg/tests/pass/circuits/member_static_function.leo @@ -0,0 +1,11 @@ +circuit Foo { + function echo(x: u32) -> u32 { + return x + } +} + +function main() { + let a = Foo::echo(1u32); + + console.assert(a == 1u32); +} \ No newline at end of file diff --git a/asg/tests/pass/circuits/member_static_function_nested.leo b/asg/tests/pass/circuits/member_static_function_nested.leo new file mode 100644 index 0000000000..ef536e3f6e --- /dev/null +++ b/asg/tests/pass/circuits/member_static_function_nested.leo @@ -0,0 +1,15 @@ +circuit Foo { + function qux() {} + + function bar() { + Self::qux(); + } + + function baz() { + Self::bar(); + } +} + +function main() { + Foo::baz(); +} \ No newline at end of file diff --git a/asg/tests/pass/circuits/member_variable.leo b/asg/tests/pass/circuits/member_variable.leo new file mode 100644 index 0000000000..0dd35f2aec --- /dev/null +++ b/asg/tests/pass/circuits/member_variable.leo @@ -0,0 +1,9 @@ +circuit Foo { + x: u32, +} + +function main() { + let a = Foo { x: 1u32 }; + + console.assert(a.x == 1u32); +} \ No newline at end of file diff --git a/asg/tests/pass/circuits/member_variable_and_function.leo b/asg/tests/pass/circuits/member_variable_and_function.leo new file mode 100644 index 0000000000..074feab7b8 --- /dev/null +++ b/asg/tests/pass/circuits/member_variable_and_function.leo @@ -0,0 +1,15 @@ +circuit Foo { + foo: u32, + + function bar() -> u32 { + return 1u32 + } +} + +function main() { + let a = Foo { foo: 1 }; + + let b = a.foo + Foo::bar(); + + console.assert(b == 2u32); +} diff --git a/asg/tests/pass/circuits/mod.rs b/asg/tests/pass/circuits/mod.rs new file mode 100644 index 0000000000..00d3aa0270 --- /dev/null +++ b/asg/tests/pass/circuits/mod.rs @@ -0,0 +1,138 @@ +// 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 . + +// 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 . + +use crate::load_asg; + +// Expressions + +#[test] +fn test_inline() { + let program_string = include_str!("inline.leo"); + load_asg(program_string).unwrap(); +} + +// Members + +#[test] +fn test_member_variable() { + let program_string = include_str!("member_variable.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_member_variable_and_function() { + let program_string = include_str!("member_variable_and_function.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_member_function() { + let program_string = include_str!("member_function.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_mut_member_function() { + let program_string = r#" + circuit Foo { + function echo(mut self, x: u32) -> u32 { + return x + } + } + + function main() { + let mut a = Foo { }; + + console.assert(a.echo(1u32) == 1u32); + }"#; + load_asg(program_string).unwrap(); +} + +#[test] +fn test_member_function_nested() { + let program_string = include_str!("member_function_nested.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_member_static_function() { + let program_string = include_str!("member_static_function.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_member_static_function_nested() { + let program_string = include_str!("member_static_function_nested.leo"); + load_asg(program_string).unwrap(); +} + +// Mutability + +#[test] +fn test_mutate_self_variable() { + let program_string = include_str!("mut_self_variable.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_mutate_self_variable_conditional() { + let program_string = include_str!("mut_self_variable_conditional.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_mutate_variable() { + let program_string = include_str!("mut_variable.leo"); + load_asg(program_string).unwrap(); +} + +// Self + +#[test] +fn test_self_member_pass() { + let program_string = include_str!("self_member.leo"); + load_asg(program_string).unwrap(); +} + +// All + +#[test] +fn test_pedersen_mock() { + let program_string = include_str!("pedersen_mock.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_define_circuit_inside_circuit_function() { + let program_string = include_str!("define_circuit_inside_circuit_function.leo"); + load_asg(program_string).unwrap(); +} diff --git a/asg/tests/pass/circuits/mut_self_variable.leo b/asg/tests/pass/circuits/mut_self_variable.leo new file mode 100644 index 0000000000..f5a35ec754 --- /dev/null +++ b/asg/tests/pass/circuits/mut_self_variable.leo @@ -0,0 +1,22 @@ +circuit Foo { + a: u8, + + function set_a(mut self, new: u8) { + self.a = new; + console.assert(self.a == new); + } +} + +function main() { + let mut f = Foo { a: 0u8 }; + + console.assert(f.a == 0u8); + + f.set_a(1u8); + + console.assert(f.a == 1u8); + + f.set_a(2u8); + + console.assert(f.a == 2u8); +} \ No newline at end of file diff --git a/asg/tests/pass/circuits/mut_self_variable_conditional.leo b/asg/tests/pass/circuits/mut_self_variable_conditional.leo new file mode 100644 index 0000000000..74345afcb4 --- /dev/null +++ b/asg/tests/pass/circuits/mut_self_variable_conditional.leo @@ -0,0 +1,15 @@ +function main() { + let mut f = Foo { a: 0u32 }; + + f.bar(); +} + +circuit Foo { + a: u32 + + function bar(mut self) { + if true { + self.a = 5u32; // Mutating a variable inside a conditional statement should work. + } + } +} \ No newline at end of file diff --git a/asg/tests/pass/circuits/mut_variable.leo b/asg/tests/pass/circuits/mut_variable.leo new file mode 100644 index 0000000000..243d7a2cf2 --- /dev/null +++ b/asg/tests/pass/circuits/mut_variable.leo @@ -0,0 +1,17 @@ +circuit Foo { + a: u8, +} + +function main() { + let mut f = Foo { a: 0u8 }; + + console.assert(f.a == 0u8); + + f.a = 1u8; + + console.assert(f.a == 1u8); + + f.a = 2u8; + + console.assert(f.a == 2u8); +} \ No newline at end of file diff --git a/asg/tests/pass/circuits/pedersen_mock.leo b/asg/tests/pass/circuits/pedersen_mock.leo new file mode 100644 index 0000000000..0b42c64a6e --- /dev/null +++ b/asg/tests/pass/circuits/pedersen_mock.leo @@ -0,0 +1,27 @@ +circuit PedersenHash { + parameters: [u32; 512] + + function new(parameters: [u32; 512]) -> Self { + return Self { parameters: parameters } + } + + function hash(self, bits: [bool; 512]) -> u32 { + let mut digest: u32 = 0; + for i in 0..512 { + let base = if bits[i] ? self.parameters[i] : 0u32; + digest += base; + } + return digest + } +} + +// The 'pedersen_hash' main function. +function main() { + let parameters = [0u32; 512]; + let pedersen = PedersenHash::new(parameters); + let hash_input: [bool; 512] = [true; 512]; + + let res = pedersen.hash(hash_input); + + console.assert(res == 0u32); +} diff --git a/asg/tests/pass/circuits/self_circuit.leo b/asg/tests/pass/circuits/self_circuit.leo new file mode 100644 index 0000000000..5a1d6c63be --- /dev/null +++ b/asg/tests/pass/circuits/self_circuit.leo @@ -0,0 +1,9 @@ +circuit Foo { + static function new() -> Self { + return Self { } + } +} + +function main() { + let a = Foo::new(); +} \ No newline at end of file diff --git a/asg/tests/pass/circuits/self_member.leo b/asg/tests/pass/circuits/self_member.leo new file mode 100644 index 0000000000..1bd978433d --- /dev/null +++ b/asg/tests/pass/circuits/self_member.leo @@ -0,0 +1,14 @@ +circuit Foo { + f: u32, + + function bar(self) -> u32 { + return self.f + } +} + +function main() { + let a = Foo { f: 1u32 }; + let b = a.bar(); + + console.assert(b == 1u32); +} \ No newline at end of file diff --git a/asg/tests/pass/console/assert.leo b/asg/tests/pass/console/assert.leo new file mode 100644 index 0000000000..ba6be77256 --- /dev/null +++ b/asg/tests/pass/console/assert.leo @@ -0,0 +1,3 @@ +function main(a: bool) { + console.assert(a == true); +} \ No newline at end of file diff --git a/asg/tests/pass/console/conditional_assert.leo b/asg/tests/pass/console/conditional_assert.leo new file mode 100644 index 0000000000..f2c1591e9c --- /dev/null +++ b/asg/tests/pass/console/conditional_assert.leo @@ -0,0 +1,7 @@ +function main(a: bool) { + if a { + console.assert(a == true); + } else { + console.assert(a == false); + } +} \ No newline at end of file diff --git a/asg/tests/pass/console/debug.leo b/asg/tests/pass/console/debug.leo new file mode 100644 index 0000000000..54e6eb539f --- /dev/null +++ b/asg/tests/pass/console/debug.leo @@ -0,0 +1,3 @@ +function main() { + console.debug("hello debug"); +} \ No newline at end of file diff --git a/asg/tests/pass/console/error.leo b/asg/tests/pass/console/error.leo new file mode 100644 index 0000000000..86d13f8cee --- /dev/null +++ b/asg/tests/pass/console/error.leo @@ -0,0 +1,3 @@ +function main() { + console.error("hello error"); +} \ No newline at end of file diff --git a/asg/tests/pass/console/log.leo b/asg/tests/pass/console/log.leo new file mode 100644 index 0000000000..a190ca4ba9 --- /dev/null +++ b/asg/tests/pass/console/log.leo @@ -0,0 +1,3 @@ +function main() { + console.log("hello world"); +} \ No newline at end of file diff --git a/asg/tests/pass/console/log_fail.leo b/asg/tests/pass/console/log_fail.leo new file mode 100644 index 0000000000..dafa6bea8e --- /dev/null +++ b/asg/tests/pass/console/log_fail.leo @@ -0,0 +1,3 @@ +function main() { + console.log( hello ); +} \ No newline at end of file diff --git a/asg/tests/pass/console/log_input.leo b/asg/tests/pass/console/log_input.leo new file mode 100644 index 0000000000..c4fd0a8b12 --- /dev/null +++ b/asg/tests/pass/console/log_input.leo @@ -0,0 +1,3 @@ +function main(a: bool) { + console.log("a = {}", a); +} \ No newline at end of file diff --git a/asg/tests/pass/console/log_parameter.leo b/asg/tests/pass/console/log_parameter.leo new file mode 100644 index 0000000000..ebcb931a2b --- /dev/null +++ b/asg/tests/pass/console/log_parameter.leo @@ -0,0 +1,3 @@ +function main() { + console.log("{}", 1u32); +} \ No newline at end of file diff --git a/asg/tests/pass/console/log_parameter_fail_empty.leo b/asg/tests/pass/console/log_parameter_fail_empty.leo new file mode 100644 index 0000000000..81b42c0919 --- /dev/null +++ b/asg/tests/pass/console/log_parameter_fail_empty.leo @@ -0,0 +1,3 @@ +function main() { + console.log("{}"); +} \ No newline at end of file diff --git a/asg/tests/pass/console/log_parameter_fail_none.leo b/asg/tests/pass/console/log_parameter_fail_none.leo new file mode 100644 index 0000000000..c92fdfbb2d --- /dev/null +++ b/asg/tests/pass/console/log_parameter_fail_none.leo @@ -0,0 +1,3 @@ +function main() { + console.log("", 1u32); +} \ No newline at end of file diff --git a/asg/tests/pass/console/log_parameter_fail_unknown.leo b/asg/tests/pass/console/log_parameter_fail_unknown.leo new file mode 100644 index 0000000000..757f4c27c3 --- /dev/null +++ b/asg/tests/pass/console/log_parameter_fail_unknown.leo @@ -0,0 +1,3 @@ +function main() { + console.log("{}", a); +} \ No newline at end of file diff --git a/asg/tests/pass/console/log_parameter_many.leo b/asg/tests/pass/console/log_parameter_many.leo new file mode 100644 index 0000000000..60455ebbb0 --- /dev/null +++ b/asg/tests/pass/console/log_parameter_many.leo @@ -0,0 +1,3 @@ +function main() { + console.log("{} {}", 1u32, true); +} \ No newline at end of file diff --git a/asg/tests/pass/console/mod.rs b/asg/tests/pass/console/mod.rs new file mode 100644 index 0000000000..b32fc56ff2 --- /dev/null +++ b/asg/tests/pass/console/mod.rs @@ -0,0 +1,87 @@ +// 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 . + +// 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 . + +use crate::load_asg; + +#[test] +fn test_log() { + let program_string = include_str!("log.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_log_parameter() { + let program_string = include_str!("log_parameter.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_log_parameter_many() { + let program_string = include_str!("log_parameter_many.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_log_input() { + let program_string = include_str!("log_input.leo"); + load_asg(program_string).unwrap(); +} + +// Debug + +#[test] +fn test_debug() { + let program_string = include_str!("debug.leo"); + load_asg(program_string).unwrap(); +} + +// Error + +#[test] +fn test_error() { + let program_string = include_str!("error.leo"); + load_asg(program_string).unwrap(); +} + +// Assertion + +#[test] +fn test_assert() { + let program_string = include_str!("assert.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_conditional_assert() { + let program_string = include_str!("conditional_assert.leo"); + load_asg(program_string).unwrap(); +} diff --git a/asg/tests/pass/core/blake2s_input.leo b/asg/tests/pass/core/blake2s_input.leo new file mode 100644 index 0000000000..6044795c3d --- /dev/null +++ b/asg/tests/pass/core/blake2s_input.leo @@ -0,0 +1,5 @@ +import core.unstable.blake2s.Blake2s; + +function main(seed: [u8; 32], message: [u8; 32]) -> [u8; 32] { + return Blake2s::hash(seed, message) +} diff --git a/asg/tests/pass/core/blake2s_random.leo b/asg/tests/pass/core/blake2s_random.leo new file mode 100644 index 0000000000..72aef44932 --- /dev/null +++ b/asg/tests/pass/core/blake2s_random.leo @@ -0,0 +1,7 @@ +import core.unstable.blake2s.Blake2s; + +function main(seed: [u8; 32], message: [u8; 32], expected: [u8; 32]) { + let actual = Blake2s::hash(seed, message); + + console.assert(expected == actual); +} diff --git a/asg/tests/pass/core/mod.rs b/asg/tests/pass/core/mod.rs new file mode 100644 index 0000000000..edceb6112e --- /dev/null +++ b/asg/tests/pass/core/mod.rs @@ -0,0 +1,51 @@ +// 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 . + +// 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 . + +use crate::load_asg; + +#[test] +fn test_unstable_blake2s() { + let program_string = include_str!("unstable_blake2s.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_blake2s_input() { + let program_string = include_str!("blake2s_input.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_blake2s_random() { + let program_string = include_str!("blake2s_random.leo"); + load_asg(program_string).unwrap(); +} diff --git a/asg/tests/pass/core/unstable_blake2s.leo b/asg/tests/pass/core/unstable_blake2s.leo new file mode 100644 index 0000000000..ca7db13892 --- /dev/null +++ b/asg/tests/pass/core/unstable_blake2s.leo @@ -0,0 +1,10 @@ +import core.unstable.blake2s.Blake2s; + +function main() { + let seed: [u8; 32] = [0; 32]; + let message: [u8; 32] = [0; 32]; + + let result = Blake2s::hash(seed, message); + + console.log("Result: {}", result); +} diff --git a/asg/tests/pass/definition/mod.rs b/asg/tests/pass/definition/mod.rs new file mode 100644 index 0000000000..ebf69c6a66 --- /dev/null +++ b/asg/tests/pass/definition/mod.rs @@ -0,0 +1,46 @@ +// 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 . + +// 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 . + +use crate::load_asg; + +#[test] +fn test_out_of_order() { + let program_string = include_str!("out_of_order.leo"); + load_asg(program_string).unwrap(); +} + +// #[test] +// #[ignore] +// fn test_out_of_order_with_import() { +// let program_string = include_str!("out_of_order_with_import.leo"); +// load_asg(program_string).unwrap(); +// } diff --git a/asg/tests/pass/definition/out_of_order.leo b/asg/tests/pass/definition/out_of_order.leo new file mode 100644 index 0000000000..69d46d0e74 --- /dev/null +++ b/asg/tests/pass/definition/out_of_order.leo @@ -0,0 +1,6 @@ +@test +function fake_test() {} + +function main() {} + +circuit Foo {} \ No newline at end of file diff --git a/asg/tests/pass/definition/out_of_order_with_import.leo b/asg/tests/pass/definition/out_of_order_with_import.leo new file mode 100644 index 0000000000..9da2938c08 --- /dev/null +++ b/asg/tests/pass/definition/out_of_order_with_import.leo @@ -0,0 +1,8 @@ +@test +function fake_test() {} + +function main() {} + +import test_import.foo; + +circuit Foo {} \ No newline at end of file diff --git a/asg/tests/pass/field/add.leo b/asg/tests/pass/field/add.leo new file mode 100644 index 0000000000..8dc2c7df4e --- /dev/null +++ b/asg/tests/pass/field/add.leo @@ -0,0 +1,3 @@ +function main(a: field, b: field, c: field) { + console.assert(a + b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/field/console_assert.leo b/asg/tests/pass/field/console_assert.leo new file mode 100644 index 0000000000..c7224bcea5 --- /dev/null +++ b/asg/tests/pass/field/console_assert.leo @@ -0,0 +1,3 @@ +function main(a: field, b: field) { + console.assert(a == b); +} \ No newline at end of file diff --git a/asg/tests/pass/field/div.leo b/asg/tests/pass/field/div.leo new file mode 100644 index 0000000000..028b06fad2 --- /dev/null +++ b/asg/tests/pass/field/div.leo @@ -0,0 +1,3 @@ +function main(a: field, b: field, c: field) { + console.assert(a / b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/field/eq.leo b/asg/tests/pass/field/eq.leo new file mode 100644 index 0000000000..e64307d8de --- /dev/null +++ b/asg/tests/pass/field/eq.leo @@ -0,0 +1,3 @@ +function main(a: field, b: field, c: bool) { + console.assert(a == b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/field/mod.rs b/asg/tests/pass/field/mod.rs new file mode 100644 index 0000000000..3401e24e14 --- /dev/null +++ b/asg/tests/pass/field/mod.rs @@ -0,0 +1,81 @@ +// 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 . + +// 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 . + +use crate::load_asg; + +#[test] +fn test_negate() { + let program_string = include_str!("negate.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_add() { + let program_string = include_str!("add.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_sub() { + let program_string = include_str!("sub.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_div() { + let program_string = include_str!("div.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_mul() { + let program_string = include_str!("mul.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_eq() { + let program_string = include_str!("eq.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_console_assert_pass() { + let program_string = include_str!("console_assert.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_ternary() { + let program_string = include_str!("ternary.leo"); + load_asg(program_string).unwrap(); +} diff --git a/asg/tests/pass/field/mul.leo b/asg/tests/pass/field/mul.leo new file mode 100644 index 0000000000..7df7c83830 --- /dev/null +++ b/asg/tests/pass/field/mul.leo @@ -0,0 +1,3 @@ +function main(a: field, b: field, c: field) { + console.assert(a * b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/field/negate.leo b/asg/tests/pass/field/negate.leo new file mode 100644 index 0000000000..94c730207a --- /dev/null +++ b/asg/tests/pass/field/negate.leo @@ -0,0 +1,3 @@ +function main(a: field, b: field) { + console.assert(-a == b); +} \ No newline at end of file diff --git a/asg/tests/pass/field/sub.leo b/asg/tests/pass/field/sub.leo new file mode 100644 index 0000000000..2c84b24647 --- /dev/null +++ b/asg/tests/pass/field/sub.leo @@ -0,0 +1,3 @@ +function main(a: field, b: field, c: field) { + console.assert(a - b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/field/ternary.leo b/asg/tests/pass/field/ternary.leo new file mode 100644 index 0000000000..49cd6a4e62 --- /dev/null +++ b/asg/tests/pass/field/ternary.leo @@ -0,0 +1,5 @@ +function main(s: bool, a: field, b: field, c: field) { + let r = if s ? a : b; + + console.assert(r == c); +} \ No newline at end of file diff --git a/asg/tests/pass/form_ast.rs b/asg/tests/pass/form_ast.rs new file mode 100644 index 0000000000..58f00119fb --- /dev/null +++ b/asg/tests/pass/form_ast.rs @@ -0,0 +1,88 @@ +// 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 . + +use crate::load_asg; + +#[test] +fn test_basic() { + let program_string = include_str!("./circuits/pedersen_mock.leo"); + let asg = load_asg(program_string).unwrap(); + let reformed_ast = leo_asg::reform_ast(&asg); + println!("{}", reformed_ast); + // panic!(); +} + +#[test] +fn test_function_rename() { + let program_string = r#" + function iteration() -> u32 { + let mut a = 0u32; + + for i in 0..10 { + a += 1; + } + + return a + } + + function main() { + let total = iteration() + iteration(); + + console.assert(total == 20); + } + "#; + let asg = load_asg(program_string).unwrap(); + let reformed_ast = leo_asg::reform_ast(&asg); + println!("{}", reformed_ast); + // panic!(); +} + +#[test] +fn test_imports() { + let mut imports = crate::mocked_resolver(); + let test_import = r#" + circuit Point { + x: u32 + y: u32 + } + + function foo() -> u32 { + return 1u32 + } + "#; + imports + .packages + .insert("test-import".to_string(), load_asg(test_import).unwrap()); + let program_string = r#" + import test-import.foo; + + function main() { + console.assert(foo() == 1u32); + } + "#; + println!( + "{}", + serde_json::to_string(&crate::load_ast("test-import.leo", test_import).unwrap()).unwrap() + ); + println!( + "{}", + serde_json::to_string(&crate::load_ast("test.leo", program_string).unwrap()).unwrap() + ); + let asg = crate::load_asg_imports(program_string, &mut imports).unwrap(); + let reformed_ast = leo_asg::reform_ast(&asg); + println!("{}", serde_json::to_string(&reformed_ast).unwrap()); + // panic!(); +} diff --git a/asg/tests/pass/function/array_input.leo b/asg/tests/pass/function/array_input.leo new file mode 100644 index 0000000000..a70483cae7 --- /dev/null +++ b/asg/tests/pass/function/array_input.leo @@ -0,0 +1,6 @@ +function foo(a: [u8; 1]) {} + +function main() { + let a: [u16; 1] = [1; 1]; + foo(a); +} \ No newline at end of file diff --git a/asg/tests/pass/function/empty.leo b/asg/tests/pass/function/empty.leo new file mode 100644 index 0000000000..f06c976158 --- /dev/null +++ b/asg/tests/pass/function/empty.leo @@ -0,0 +1,5 @@ +function empty() { } + +function main() { + empty(); +} \ No newline at end of file diff --git a/asg/tests/pass/function/iteration.leo b/asg/tests/pass/function/iteration.leo new file mode 100644 index 0000000000..19af4dd9cf --- /dev/null +++ b/asg/tests/pass/function/iteration.leo @@ -0,0 +1,13 @@ +function one() -> u32 { + return 1u32 +} + +function main() { + let mut a = 0u32; + + for i in 0..10 { + a += one(); + } + + console.assert(a == 10u32); +} \ No newline at end of file diff --git a/asg/tests/pass/function/iteration_repeated.leo b/asg/tests/pass/function/iteration_repeated.leo new file mode 100644 index 0000000000..3694b3594a --- /dev/null +++ b/asg/tests/pass/function/iteration_repeated.leo @@ -0,0 +1,15 @@ +function iteration() -> u32 { + let mut a = 0u32; + + for i in 0..10 { + a += 1; + } + + return a +} + +function main() { + let total = iteration() + iteration(); + + console.assert(total == 20); +} \ No newline at end of file diff --git a/asg/tests/pass/function/mod.rs b/asg/tests/pass/function/mod.rs new file mode 100644 index 0000000000..456d5e7dd1 --- /dev/null +++ b/asg/tests/pass/function/mod.rs @@ -0,0 +1,127 @@ +// 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 . + +// 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 . + +use crate::load_asg; + +#[test] +fn test_empty() { + let program_string = include_str!("empty.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_iteration() { + let program_string = include_str!("iteration.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_iteration_repeated() { + let program_string = include_str!("iteration_repeated.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_newlines() { + let program_string = include_str!("newlines.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_multiple_returns() { + let program_string = include_str!("multiple_returns.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_multiple_returns_main() { + let program_string = include_str!("multiple_returns_main.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_repeated_function_call() { + let program_string = include_str!("repeated.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_return() { + let program_string = include_str!("return.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_undefined() { + let program_string = include_str!("undefined.leo"); + load_asg(program_string).err().unwrap(); +} + +#[test] +fn test_value_unchanged() { + let program_string = include_str!("value_unchanged.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_array_input() { + let program_string = include_str!("array_input.leo"); + load_asg(program_string).err().unwrap(); +} + +// Test return multidimensional arrays + +#[test] +fn test_return_array_nested_pass() { + let program_string = include_str!("return_array_nested_pass.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_return_array_tuple_pass() { + let program_string = include_str!("return_array_tuple_pass.leo"); + load_asg(program_string).unwrap(); +} + +// Test return tuples + +#[test] +fn test_return_tuple() { + let program_string = include_str!("return_tuple.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_return_tuple_conditional() { + let program_string = include_str!("return_tuple_conditional.leo"); + load_asg(program_string).unwrap(); +} diff --git a/asg/tests/pass/function/multiple_returns.leo b/asg/tests/pass/function/multiple_returns.leo new file mode 100644 index 0000000000..ef00a4ef47 --- /dev/null +++ b/asg/tests/pass/function/multiple_returns.leo @@ -0,0 +1,10 @@ +function tuple() -> (bool, bool) { + return (true, false) +} + +function main() { + let (a, b) = tuple(); + + console.assert(a == true); + console.assert(b == false); +} \ No newline at end of file diff --git a/asg/tests/pass/function/multiple_returns_main.leo b/asg/tests/pass/function/multiple_returns_main.leo new file mode 100644 index 0000000000..0bc82e1e4b --- /dev/null +++ b/asg/tests/pass/function/multiple_returns_main.leo @@ -0,0 +1,3 @@ +function main(input) -> (bool, bool) { + return (input.registers.a, input.registers.b) +} \ No newline at end of file diff --git a/asg/tests/pass/function/newlines.leo b/asg/tests/pass/function/newlines.leo new file mode 100644 index 0000000000..8c703f81d3 --- /dev/null +++ b/asg/tests/pass/function/newlines.leo @@ -0,0 +1,9 @@ +function main( + a: u32, + b: u32, +) -> ( + u32, + u32, +) { + return (a, b) +} \ No newline at end of file diff --git a/asg/tests/pass/function/repeated.leo b/asg/tests/pass/function/repeated.leo new file mode 100644 index 0000000000..a2d04d55f9 --- /dev/null +++ b/asg/tests/pass/function/repeated.leo @@ -0,0 +1,9 @@ +function one() -> bool { + return true +} + +function main() { + let a = one() && one(); + + console.assert(a == true); +} \ No newline at end of file diff --git a/asg/tests/pass/function/return.leo b/asg/tests/pass/function/return.leo new file mode 100644 index 0000000000..10c7138977 --- /dev/null +++ b/asg/tests/pass/function/return.leo @@ -0,0 +1,7 @@ +function one() -> u32 { + return 1u32 +} + +function main() { + console.assert(one() == 1u32); +} \ No newline at end of file diff --git a/asg/tests/pass/function/return_array_nested_pass.leo b/asg/tests/pass/function/return_array_nested_pass.leo new file mode 100644 index 0000000000..dda5b4342b --- /dev/null +++ b/asg/tests/pass/function/return_array_nested_pass.leo @@ -0,0 +1,12 @@ +function array_3x2_nested() -> [[u8; 2]; 3] { + return [[0u8; 2]; 3] +} + +function array_3x2_tuple() -> [[u8; 2]; 3] { + return [0u8; (3, 2)] +} + +function main() { + let a = array_3x2_nested(); + let b = array_3x2_tuple(); +} \ No newline at end of file diff --git a/asg/tests/pass/function/return_array_tuple_pass.leo b/asg/tests/pass/function/return_array_tuple_pass.leo new file mode 100644 index 0000000000..a700bcabad --- /dev/null +++ b/asg/tests/pass/function/return_array_tuple_pass.leo @@ -0,0 +1,12 @@ +function array_3x2_nested() -> [u8; (3, 2)] { + return [[0u8; 2]; 3] +} + +function array_3x2_tuple() -> [u8; (3, 2)] { + return [0u8; (3, 2)] +} + +function main() { + let a = array_3x2_nested(); + let b = array_3x2_tuple(); +} \ No newline at end of file diff --git a/asg/tests/pass/function/return_tuple.leo b/asg/tests/pass/function/return_tuple.leo new file mode 100644 index 0000000000..c459740a47 --- /dev/null +++ b/asg/tests/pass/function/return_tuple.leo @@ -0,0 +1,11 @@ +// Returns a tuple of tuples. +function tuples() -> ((u8, u8), u32) { + let a: (u8, u8) = (1, 2); + let b: u32 = 3; + + return (a, b) +} + +function main() { + let t = tuples(); +} \ No newline at end of file diff --git a/asg/tests/pass/function/return_tuple_conditional.leo b/asg/tests/pass/function/return_tuple_conditional.leo new file mode 100644 index 0000000000..c63967f548 --- /dev/null +++ b/asg/tests/pass/function/return_tuple_conditional.leo @@ -0,0 +1,15 @@ +// Returns a tuple using a conditional "if" statement. +function tuple_conditional () -> ( + i64, + i64 +) { + if true { + return (1, 1) + } else { + return (2, 2) + } +} + +function main() { + let t = tuple_conditional(); +} \ No newline at end of file diff --git a/asg/tests/pass/function/undefined.leo b/asg/tests/pass/function/undefined.leo new file mode 100644 index 0000000000..e1db3b9f09 --- /dev/null +++ b/asg/tests/pass/function/undefined.leo @@ -0,0 +1,3 @@ +function main() { + my_function(); +} \ No newline at end of file diff --git a/asg/tests/pass/function/value_unchanged.leo b/asg/tests/pass/function/value_unchanged.leo new file mode 100644 index 0000000000..32dcfa62d6 --- /dev/null +++ b/asg/tests/pass/function/value_unchanged.leo @@ -0,0 +1,19 @@ +// Functions input in leo are pass-by-value. +// +// Program execution: +// line 15: variable `a` is defined with value `1`. +// line 16: value `1` is copied and passed into function `bad_mutate()`. +// line 10: variable `x` is defined with value `1`. +// line 11: variable `x` is set to value `0`. +// line 18: program returns the value of `a`. + +function bad_mutate(mut x: u32) { + x = 0; // <- does not change `a` +} + +function main() { + let a = 1u32; + bad_mutate(a); + + console.assert(a == 1u32); // <- value `a` is still `1u32` +} \ No newline at end of file diff --git a/asg/tests/pass/group/add.leo b/asg/tests/pass/group/add.leo new file mode 100644 index 0000000000..bb84df2d6c --- /dev/null +++ b/asg/tests/pass/group/add.leo @@ -0,0 +1,3 @@ +function main(a: group, b: group, c: group) { + console.assert(a + b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/group/assert_eq.leo b/asg/tests/pass/group/assert_eq.leo new file mode 100644 index 0000000000..3886a07bbf --- /dev/null +++ b/asg/tests/pass/group/assert_eq.leo @@ -0,0 +1,3 @@ +function main(a: group, b: group) { + console.assert(a == b); +} \ No newline at end of file diff --git a/asg/tests/pass/group/both_sign_high.leo b/asg/tests/pass/group/both_sign_high.leo new file mode 100644 index 0000000000..a8217d6d40 --- /dev/null +++ b/asg/tests/pass/group/both_sign_high.leo @@ -0,0 +1,3 @@ +function main() { + let element = (+, +)group; +} \ No newline at end of file diff --git a/asg/tests/pass/group/both_sign_inferred.leo b/asg/tests/pass/group/both_sign_inferred.leo new file mode 100644 index 0000000000..b3b8b512c3 --- /dev/null +++ b/asg/tests/pass/group/both_sign_inferred.leo @@ -0,0 +1,3 @@ +function main() { + let element = (_, _)group; +} \ No newline at end of file diff --git a/asg/tests/pass/group/both_sign_low.leo b/asg/tests/pass/group/both_sign_low.leo new file mode 100644 index 0000000000..0519c6d17d --- /dev/null +++ b/asg/tests/pass/group/both_sign_low.leo @@ -0,0 +1,3 @@ +function main() { + let element = (-, -)group; +} \ No newline at end of file diff --git a/asg/tests/pass/group/eq.leo b/asg/tests/pass/group/eq.leo new file mode 100644 index 0000000000..89701d9c99 --- /dev/null +++ b/asg/tests/pass/group/eq.leo @@ -0,0 +1,3 @@ +function main(a: group, b: group, c: bool) { + console.assert(a == b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/group/input.leo b/asg/tests/pass/group/input.leo new file mode 100644 index 0000000000..3886a07bbf --- /dev/null +++ b/asg/tests/pass/group/input.leo @@ -0,0 +1,3 @@ +function main(a: group, b: group) { + console.assert(a == b); +} \ No newline at end of file diff --git a/asg/tests/pass/group/mod.rs b/asg/tests/pass/group/mod.rs new file mode 100644 index 0000000000..c800104bc9 --- /dev/null +++ b/asg/tests/pass/group/mod.rs @@ -0,0 +1,135 @@ +// 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 . + +// 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 . + +use crate::load_asg; + +#[test] +fn test_one() { + let program_string = include_str!("one.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_zero() { + let program_string = include_str!("zero.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_point() { + let program_string = include_str!("point.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_x_sign_high() { + let program_string = include_str!("x_sign_high.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_x_sign_low() { + let program_string = include_str!("x_sign_low.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_x_sign_inferred() { + let program_string = include_str!("x_sign_inferred.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_y_sign_high() { + let program_string = include_str!("y_sign_high.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_y_sign_low() { + let program_string = include_str!("y_sign_low.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_y_sign_inferred() { + let program_string = include_str!("y_sign_inferred.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_point_input() { + let program_string = include_str!("point_input.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_input() { + let program_string = include_str!("input.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_negate() { + let program_string = include_str!("negate.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_add() { + let program_string = include_str!("add.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_sub() { + let program_string = include_str!("sub.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_console_assert_pass() { + let program_string = include_str!("assert_eq.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_eq() { + let program_string = include_str!("eq.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_ternary() { + let program_string = include_str!("ternary.leo"); + load_asg(program_string).unwrap(); +} diff --git a/asg/tests/pass/group/negate.leo b/asg/tests/pass/group/negate.leo new file mode 100644 index 0000000000..506d8d73ce --- /dev/null +++ b/asg/tests/pass/group/negate.leo @@ -0,0 +1,3 @@ +function main(a: group, b: group) { + console.assert(-a == b); +} \ No newline at end of file diff --git a/asg/tests/pass/group/one.leo b/asg/tests/pass/group/one.leo new file mode 100644 index 0000000000..7be0cbbc2c --- /dev/null +++ b/asg/tests/pass/group/one.leo @@ -0,0 +1,3 @@ +function main() { + let element = 1group; +} \ No newline at end of file diff --git a/asg/tests/pass/group/point.leo b/asg/tests/pass/group/point.leo new file mode 100644 index 0000000000..5e68415a0d --- /dev/null +++ b/asg/tests/pass/group/point.leo @@ -0,0 +1,3 @@ +function main() { + const point = (7374112779530666882856915975292384652154477718021969292781165691637980424078, 3435195339177955418892975564890903138308061187980579490487898366607011481796)group; +} \ No newline at end of file diff --git a/asg/tests/pass/group/point_input.leo b/asg/tests/pass/group/point_input.leo new file mode 100644 index 0000000000..68d8c458a3 --- /dev/null +++ b/asg/tests/pass/group/point_input.leo @@ -0,0 +1,3 @@ +function main(a: group) { + let b = a; +} \ No newline at end of file diff --git a/asg/tests/pass/group/sub.leo b/asg/tests/pass/group/sub.leo new file mode 100644 index 0000000000..dfe82d8e31 --- /dev/null +++ b/asg/tests/pass/group/sub.leo @@ -0,0 +1,3 @@ +function main(a: group, b: group, c: group) { + console.assert(a - b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/group/ternary.leo b/asg/tests/pass/group/ternary.leo new file mode 100644 index 0000000000..b213bb1419 --- /dev/null +++ b/asg/tests/pass/group/ternary.leo @@ -0,0 +1,5 @@ +function main(s: bool, a: group, b: group, c: group) { + let r = if s ? a : b; + + console.assert(r == c); +} \ No newline at end of file diff --git a/asg/tests/pass/group/x_and_y.leo b/asg/tests/pass/group/x_and_y.leo new file mode 100644 index 0000000000..1b64702db1 --- /dev/null +++ b/asg/tests/pass/group/x_and_y.leo @@ -0,0 +1,3 @@ +function main(element: group) { + let b = element; +} \ No newline at end of file diff --git a/asg/tests/pass/group/x_sign_high.leo b/asg/tests/pass/group/x_sign_high.leo new file mode 100644 index 0000000000..1b8d397d02 --- /dev/null +++ b/asg/tests/pass/group/x_sign_high.leo @@ -0,0 +1,3 @@ +function main() { + let element = (0, +)group; +} \ No newline at end of file diff --git a/asg/tests/pass/group/x_sign_inferred.leo b/asg/tests/pass/group/x_sign_inferred.leo new file mode 100644 index 0000000000..9e9622a4a4 --- /dev/null +++ b/asg/tests/pass/group/x_sign_inferred.leo @@ -0,0 +1,3 @@ +function main() { + let element = (0, _)group; +} \ No newline at end of file diff --git a/asg/tests/pass/group/x_sign_low.leo b/asg/tests/pass/group/x_sign_low.leo new file mode 100644 index 0000000000..a5058bda52 --- /dev/null +++ b/asg/tests/pass/group/x_sign_low.leo @@ -0,0 +1,3 @@ +function main() { + let element = (0, -)group; +} \ No newline at end of file diff --git a/asg/tests/pass/group/y_sign_high.leo b/asg/tests/pass/group/y_sign_high.leo new file mode 100644 index 0000000000..fe16883b39 --- /dev/null +++ b/asg/tests/pass/group/y_sign_high.leo @@ -0,0 +1,3 @@ +function main() { + let element = (+, 1)group; +} \ No newline at end of file diff --git a/asg/tests/pass/group/y_sign_inferred.leo b/asg/tests/pass/group/y_sign_inferred.leo new file mode 100644 index 0000000000..003c373cf2 --- /dev/null +++ b/asg/tests/pass/group/y_sign_inferred.leo @@ -0,0 +1,3 @@ +function main() { + let element = (_, 1)group; +} \ No newline at end of file diff --git a/asg/tests/pass/group/y_sign_low.leo b/asg/tests/pass/group/y_sign_low.leo new file mode 100644 index 0000000000..9e61bfd2bb --- /dev/null +++ b/asg/tests/pass/group/y_sign_low.leo @@ -0,0 +1,3 @@ +function main() { + let element = (-, 1)group; +} \ No newline at end of file diff --git a/asg/tests/pass/group/zero.leo b/asg/tests/pass/group/zero.leo new file mode 100644 index 0000000000..e2c0283c21 --- /dev/null +++ b/asg/tests/pass/group/zero.leo @@ -0,0 +1,3 @@ +function main() { + let element = 0group; +} \ No newline at end of file diff --git a/asg/tests/pass/import/alias.leo b/asg/tests/pass/import/alias.leo new file mode 100644 index 0000000000..f153b5a128 --- /dev/null +++ b/asg/tests/pass/import/alias.leo @@ -0,0 +1,5 @@ +import test-import.foo as bar; + +function main() { + console.assert(bar() == 1u32); +} \ No newline at end of file diff --git a/asg/tests/pass/import/basic.leo b/asg/tests/pass/import/basic.leo new file mode 100644 index 0000000000..53d243efaa --- /dev/null +++ b/asg/tests/pass/import/basic.leo @@ -0,0 +1,5 @@ +import test-import.foo; + +function main() { + console.assert(foo() == 1u32); +} \ No newline at end of file diff --git a/asg/tests/pass/import/imports/bar/.gitignore b/asg/tests/pass/import/imports/bar/.gitignore new file mode 100755 index 0000000000..ea1472ec1f --- /dev/null +++ b/asg/tests/pass/import/imports/bar/.gitignore @@ -0,0 +1 @@ +output/ diff --git a/asg/tests/pass/import/imports/bar/Leo.toml b/asg/tests/pass/import/imports/bar/Leo.toml new file mode 100755 index 0000000000..8e22d51a95 --- /dev/null +++ b/asg/tests/pass/import/imports/bar/Leo.toml @@ -0,0 +1,3 @@ +[package] +name = "bar" +version = "0.1.0" diff --git a/asg/tests/pass/import/imports/bar/src/bat/bat.leo b/asg/tests/pass/import/imports/bar/src/bat/bat.leo new file mode 100755 index 0000000000..a7d2fc83d4 --- /dev/null +++ b/asg/tests/pass/import/imports/bar/src/bat/bat.leo @@ -0,0 +1,3 @@ +circuit Bat { + t: u32 +} \ No newline at end of file diff --git a/asg/tests/pass/import/imports/bar/src/baz.leo b/asg/tests/pass/import/imports/bar/src/baz.leo new file mode 100755 index 0000000000..6c1df2d4b9 --- /dev/null +++ b/asg/tests/pass/import/imports/bar/src/baz.leo @@ -0,0 +1,3 @@ +circuit Baz { + z: u32 +} \ No newline at end of file diff --git a/asg/tests/pass/import/imports/bar/src/lib.leo b/asg/tests/pass/import/imports/bar/src/lib.leo new file mode 100755 index 0000000000..c169f5935e --- /dev/null +++ b/asg/tests/pass/import/imports/bar/src/lib.leo @@ -0,0 +1,3 @@ +circuit Bar { + r: u32 +} \ No newline at end of file diff --git a/asg/tests/pass/import/imports/car/.gitignore b/asg/tests/pass/import/imports/car/.gitignore new file mode 100755 index 0000000000..ea1472ec1f --- /dev/null +++ b/asg/tests/pass/import/imports/car/.gitignore @@ -0,0 +1 @@ +output/ diff --git a/asg/tests/pass/import/imports/car/Leo.toml b/asg/tests/pass/import/imports/car/Leo.toml new file mode 100755 index 0000000000..15b76f1d76 --- /dev/null +++ b/asg/tests/pass/import/imports/car/Leo.toml @@ -0,0 +1,3 @@ +[package] +name = "car" +version = "0.1.0" diff --git a/asg/tests/pass/import/imports/car/src/lib.leo b/asg/tests/pass/import/imports/car/src/lib.leo new file mode 100755 index 0000000000..b1e037fd38 --- /dev/null +++ b/asg/tests/pass/import/imports/car/src/lib.leo @@ -0,0 +1,3 @@ +circuit Car { + c: u32 +} \ No newline at end of file diff --git a/asg/tests/pass/import/many_import.leo b/asg/tests/pass/import/many_import.leo new file mode 100644 index 0000000000..339700fd68 --- /dev/null +++ b/asg/tests/pass/import/many_import.leo @@ -0,0 +1,25 @@ +import test-import.( // local import + Point, + foo, +); + +import bar.( // imports directory import + Bar, + baz.Baz, + bat.bat.Bat, +); + +import car.Car; // imports directory import + +function main() { + const point = Point { x: 1u32, y: 1u32 }; + const foo = foo(); + + const bar = Bar { r: 1u32 }; + const baz = Baz { z: 1u32 }; + const bat = Bat { t: 1u32 }; + + const car = Car { c: 1u32 }; + + console.assert(car.c == 1u32); +} \ No newline at end of file diff --git a/asg/tests/pass/import/many_import_star.leo b/asg/tests/pass/import/many_import_star.leo new file mode 100644 index 0000000000..575487a929 --- /dev/null +++ b/asg/tests/pass/import/many_import_star.leo @@ -0,0 +1,19 @@ +import test-import.*; // local import + +import bar.*; // imports directory import +import bar.baz.*; // imports directory import +import bar.bat.bat.*; // imports directory import +import car.*; // imports directory import + +function main() { + const point = Point { x: 1u32, y: 1u32 }; + const foo = foo(); + + const bar = Bar { r: 1u32 }; + const bat = Bat { t: 1u32 }; + const baz = Baz { z: 1u32 }; + + const car = Car { c: 1u32 }; + + console.assert(car.c == 1u32); +} \ No newline at end of file diff --git a/asg/tests/pass/import/mod.rs b/asg/tests/pass/import/mod.rs new file mode 100644 index 0000000000..41a84f8a3b --- /dev/null +++ b/asg/tests/pass/import/mod.rs @@ -0,0 +1,163 @@ +// 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 . + +// 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 . + +use crate::{load_asg, load_asg_imports, mocked_resolver}; + +#[test] +fn test_basic() { + let mut imports = mocked_resolver(); + imports.packages.insert( + "test-import".to_string(), + load_asg(include_str!("src/test-import.leo")).unwrap(), + ); + let program_string = include_str!("basic.leo"); + load_asg_imports(program_string, &mut imports).unwrap(); +} + +#[test] +fn test_multiple() { + let mut imports = mocked_resolver(); + imports.packages.insert( + "test-import".to_string(), + load_asg(include_str!("src/test-import.leo")).unwrap(), + ); + let program_string = include_str!("multiple.leo"); + load_asg_imports(program_string, &mut imports).unwrap(); +} + +#[test] +fn test_star() { + let mut imports = mocked_resolver(); + imports.packages.insert( + "test-import".to_string(), + load_asg(include_str!("src/test-import.leo")).unwrap(), + ); + + let program_string = include_str!("star.leo"); + load_asg_imports(program_string, &mut imports).unwrap(); +} + +#[test] +fn test_alias() { + let mut imports = mocked_resolver(); + imports.packages.insert( + "test-import".to_string(), + load_asg(include_str!("src/test-import.leo")).unwrap(), + ); + + let program_string = include_str!("alias.leo"); + load_asg_imports(program_string, &mut imports).unwrap(); +} + +// naming tests +#[test] +fn test_name() { + let mut imports = mocked_resolver(); + imports.packages.insert( + "hello-world".to_string(), + load_asg(include_str!("src/hello-world.leo")).unwrap(), + ); + imports + .packages + .insert("a0-f".to_string(), load_asg(include_str!("src/a0-f.leo")).unwrap()); + imports + .packages + .insert("a-9".to_string(), load_asg(include_str!("src/a-9.leo")).unwrap()); + + let program_string = include_str!("names.leo"); + load_asg_imports(program_string, &mut imports).unwrap(); +} + +// more complex tests +#[test] +fn test_many_import() { + let mut imports = mocked_resolver(); + imports.packages.insert( + "test-import".to_string(), + load_asg(include_str!("src/test-import.leo")).unwrap(), + ); + imports.packages.insert( + "bar".to_string(), + load_asg(include_str!("imports/bar/src/lib.leo")).unwrap(), + ); + imports.packages.insert( + "bar.baz".to_string(), + load_asg(include_str!("imports/bar/src/baz.leo")).unwrap(), + ); + imports.packages.insert( + "bar.baz".to_string(), + load_asg(include_str!("imports/bar/src/baz.leo")).unwrap(), + ); + imports.packages.insert( + "bar.bat.bat".to_string(), + load_asg(include_str!("imports/bar/src/bat/bat.leo")).unwrap(), + ); + imports.packages.insert( + "car".to_string(), + load_asg(include_str!("imports/car/src/lib.leo")).unwrap(), + ); + + let program_string = include_str!("many_import.leo"); + load_asg_imports(program_string, &mut imports).unwrap(); +} + +#[test] +fn test_many_import_star() { + let mut imports = mocked_resolver(); + imports.packages.insert( + "test-import".to_string(), + load_asg(include_str!("src/test-import.leo")).unwrap(), + ); + imports.packages.insert( + "bar".to_string(), + load_asg(include_str!("imports/bar/src/lib.leo")).unwrap(), + ); + imports.packages.insert( + "bar.baz".to_string(), + load_asg(include_str!("imports/bar/src/baz.leo")).unwrap(), + ); + imports.packages.insert( + "bar.baz".to_string(), + load_asg(include_str!("imports/bar/src/baz.leo")).unwrap(), + ); + imports.packages.insert( + "bar.bat.bat".to_string(), + load_asg(include_str!("imports/bar/src/bat/bat.leo")).unwrap(), + ); + imports.packages.insert( + "car".to_string(), + load_asg(include_str!("imports/car/src/lib.leo")).unwrap(), + ); + + let program_string = include_str!("many_import_star.leo"); + load_asg_imports(program_string, &mut imports).unwrap(); +} diff --git a/asg/tests/pass/import/multiple.leo b/asg/tests/pass/import/multiple.leo new file mode 100644 index 0000000000..5c89aaee0c --- /dev/null +++ b/asg/tests/pass/import/multiple.leo @@ -0,0 +1,10 @@ +import test-import.( + Point, + foo +); + +function main() { + let a = Point { x: 1u32, y: 0u32 }; + + console.assert(a.x == 1u32); +} \ No newline at end of file diff --git a/asg/tests/pass/import/names.leo b/asg/tests/pass/import/names.leo new file mode 100644 index 0000000000..d3ce50829a --- /dev/null +++ b/asg/tests/pass/import/names.leo @@ -0,0 +1,5 @@ +import a0-f.foo; +import a-9.bar; +import hello-world.hello; + +function main() {} \ No newline at end of file diff --git a/asg/tests/pass/import/src/a-9.leo b/asg/tests/pass/import/src/a-9.leo new file mode 100644 index 0000000000..8cd9f87f14 --- /dev/null +++ b/asg/tests/pass/import/src/a-9.leo @@ -0,0 +1 @@ +function bar() {} \ No newline at end of file diff --git a/asg/tests/pass/import/src/a0-f.leo b/asg/tests/pass/import/src/a0-f.leo new file mode 100644 index 0000000000..c99ad3b713 --- /dev/null +++ b/asg/tests/pass/import/src/a0-f.leo @@ -0,0 +1 @@ +function foo() {} \ No newline at end of file diff --git a/asg/tests/pass/import/src/hello-world.leo b/asg/tests/pass/import/src/hello-world.leo new file mode 100644 index 0000000000..2d96e74c4c --- /dev/null +++ b/asg/tests/pass/import/src/hello-world.leo @@ -0,0 +1 @@ +function hello() {} \ No newline at end of file diff --git a/asg/tests/pass/import/src/test-import.leo b/asg/tests/pass/import/src/test-import.leo new file mode 100644 index 0000000000..6dd3e2c88a --- /dev/null +++ b/asg/tests/pass/import/src/test-import.leo @@ -0,0 +1,8 @@ +circuit Point { + x: u32 + y: u32 +} + +function foo() -> u32 { + return 1u32 +} \ No newline at end of file diff --git a/asg/tests/pass/import/star.leo b/asg/tests/pass/import/star.leo new file mode 100644 index 0000000000..9cd817686f --- /dev/null +++ b/asg/tests/pass/import/star.leo @@ -0,0 +1,7 @@ +import test-import.*; + +function main() { + let a = Point { x: 1u32, y: 0u32 }; + + console.assert(foo() == 1u32); +} \ No newline at end of file diff --git a/asg/tests/pass/input_files/mod.rs b/asg/tests/pass/input_files/mod.rs new file mode 100644 index 0000000000..71ce8415d9 --- /dev/null +++ b/asg/tests/pass/input_files/mod.rs @@ -0,0 +1,35 @@ +// 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 . + +// 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 . + +mod program_input; +mod program_input_and_program_state; +mod program_state; diff --git a/asg/tests/pass/input_files/program_input/main.leo b/asg/tests/pass/input_files/program_input/main.leo new file mode 100644 index 0000000000..ba6be77256 --- /dev/null +++ b/asg/tests/pass/input_files/program_input/main.leo @@ -0,0 +1,3 @@ +function main(a: bool) { + console.assert(a == true); +} \ No newline at end of file diff --git a/asg/tests/pass/input_files/program_input/main_multiple.leo b/asg/tests/pass/input_files/program_input/main_multiple.leo new file mode 100644 index 0000000000..eb5ef8d1f6 --- /dev/null +++ b/asg/tests/pass/input_files/program_input/main_multiple.leo @@ -0,0 +1,4 @@ +function main(a: bool, b: bool) { + console.assert(a == true); + console.assert(b == false); +} \ No newline at end of file diff --git a/asg/tests/pass/input_files/program_input/mod.rs b/asg/tests/pass/input_files/program_input/mod.rs new file mode 100644 index 0000000000..378b635fa7 --- /dev/null +++ b/asg/tests/pass/input_files/program_input/mod.rs @@ -0,0 +1,45 @@ +// 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 . + +// 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 . + +use crate::load_asg; + +#[test] +fn test_input_pass() { + let program_string = include_str!("main.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_input_multiple() { + let program_string = include_str!("main_multiple.leo"); + load_asg(program_string).unwrap(); +} diff --git a/asg/tests/pass/input_files/program_input_and_program_state/access.leo b/asg/tests/pass/input_files/program_input_and_program_state/access.leo new file mode 100644 index 0000000000..ae1728c164 --- /dev/null +++ b/asg/tests/pass/input_files/program_input_and_program_state/access.leo @@ -0,0 +1,11 @@ +function main(input, data: [u8; 32]) { + console.assert(input.registers.value_balance == 0u64); + + console.assert(input.state.leaf_index == 0u32); + + console.assert(input.record.value == 5u64); + + console.assert(input.state_leaf.network_id == 0u8); + + console.assert(data == [0u8; 32]); +} \ No newline at end of file diff --git a/asg/tests/pass/input_files/program_input_and_program_state/mod.rs b/asg/tests/pass/input_files/program_input_and_program_state/mod.rs new file mode 100644 index 0000000000..195013cc7a --- /dev/null +++ b/asg/tests/pass/input_files/program_input_and_program_state/mod.rs @@ -0,0 +1,39 @@ +// 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 . + +// 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 . + +use crate::load_asg; + +#[test] +fn test_access() { + let program_string = include_str!("access.leo"); + load_asg(program_string).unwrap(); +} diff --git a/asg/tests/pass/input_files/program_state/access_all.leo b/asg/tests/pass/input_files/program_state/access_all.leo new file mode 100644 index 0000000000..4e7cba5776 --- /dev/null +++ b/asg/tests/pass/input_files/program_state/access_all.leo @@ -0,0 +1,8 @@ +function main(input) { + console.assert(input.state.root == [0u8; 32]); + + let expected: address = aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8; + //console.assert(input.record.owner, expected); + + console.assert(input.state_leaf.network_id == 0u8); +} \ No newline at end of file diff --git a/asg/tests/pass/input_files/program_state/access_state.leo b/asg/tests/pass/input_files/program_state/access_state.leo new file mode 100644 index 0000000000..0e014aec54 --- /dev/null +++ b/asg/tests/pass/input_files/program_state/access_state.leo @@ -0,0 +1,3 @@ +function main(input) { + console.assert(input.state.root == [0u8; 32]); +} \ No newline at end of file diff --git a/asg/tests/pass/input_files/program_state/mod.rs b/asg/tests/pass/input_files/program_state/mod.rs new file mode 100644 index 0000000000..598a513f15 --- /dev/null +++ b/asg/tests/pass/input_files/program_state/mod.rs @@ -0,0 +1,45 @@ +// 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 . + +// 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 . + +use crate::load_asg; + +#[test] +fn test_access_state() { + let program_string = include_str!("access_state.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_access_all() { + let program_string = include_str!("access_all.leo"); + load_asg(program_string).unwrap(); +} diff --git a/asg/tests/pass/integers/i128/add.leo b/asg/tests/pass/integers/i128/add.leo new file mode 100644 index 0000000000..e35648f545 --- /dev/null +++ b/asg/tests/pass/integers/i128/add.leo @@ -0,0 +1,3 @@ +function main(a: i128, b: i128, c: i128) { + console.assert(a + b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i128/console_assert.leo b/asg/tests/pass/integers/i128/console_assert.leo new file mode 100644 index 0000000000..c89021f609 --- /dev/null +++ b/asg/tests/pass/integers/i128/console_assert.leo @@ -0,0 +1,3 @@ +function main(a: i128, b: i128) { + console.assert(a == b); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i128/div.leo b/asg/tests/pass/integers/i128/div.leo new file mode 100644 index 0000000000..ffaeae19a8 --- /dev/null +++ b/asg/tests/pass/integers/i128/div.leo @@ -0,0 +1,3 @@ +function main(a: i128, b: i128, c: i128) { + console.assert(a / b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i128/eq.leo b/asg/tests/pass/integers/i128/eq.leo new file mode 100644 index 0000000000..f4beddc8fc --- /dev/null +++ b/asg/tests/pass/integers/i128/eq.leo @@ -0,0 +1,3 @@ +function main(a: i128, b: i128, c: bool) { + console.assert(a == b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i128/ge.leo b/asg/tests/pass/integers/i128/ge.leo new file mode 100644 index 0000000000..1fbbd68073 --- /dev/null +++ b/asg/tests/pass/integers/i128/ge.leo @@ -0,0 +1,3 @@ +function main(a: i128, b: i128, c: bool) { + console.assert(a >= b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i128/gt.leo b/asg/tests/pass/integers/i128/gt.leo new file mode 100644 index 0000000000..27849afbe8 --- /dev/null +++ b/asg/tests/pass/integers/i128/gt.leo @@ -0,0 +1,3 @@ +function main(a: i128, b: i128, c: bool) { + console.assert(a > b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i128/input.leo b/asg/tests/pass/integers/i128/input.leo new file mode 100644 index 0000000000..c89021f609 --- /dev/null +++ b/asg/tests/pass/integers/i128/input.leo @@ -0,0 +1,3 @@ +function main(a: i128, b: i128) { + console.assert(a == b); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i128/le.leo b/asg/tests/pass/integers/i128/le.leo new file mode 100644 index 0000000000..ea0c3c9e1d --- /dev/null +++ b/asg/tests/pass/integers/i128/le.leo @@ -0,0 +1,3 @@ +function main(a: i128, b: i128, c: bool) { + console.assert(a <= b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i128/lt.leo b/asg/tests/pass/integers/i128/lt.leo new file mode 100644 index 0000000000..bde4def85c --- /dev/null +++ b/asg/tests/pass/integers/i128/lt.leo @@ -0,0 +1,3 @@ +function main(a: i128, b: i128, c: bool) { + console.assert(a < b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i128/max.leo b/asg/tests/pass/integers/i128/max.leo new file mode 100644 index 0000000000..46c0a32599 --- /dev/null +++ b/asg/tests/pass/integers/i128/max.leo @@ -0,0 +1,3 @@ +function main() { + let a: i128 = 170141183460469231731687303715884105727; +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i128/min.leo b/asg/tests/pass/integers/i128/min.leo new file mode 100644 index 0000000000..5f32e5add5 --- /dev/null +++ b/asg/tests/pass/integers/i128/min.leo @@ -0,0 +1,3 @@ +function main() { + let a: i128 = -170141183460469231731687303715884105728; +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i128/mod.rs b/asg/tests/pass/integers/i128/mod.rs new file mode 100644 index 0000000000..522e9f2f10 --- /dev/null +++ b/asg/tests/pass/integers/i128/mod.rs @@ -0,0 +1,121 @@ +// 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 . + +// 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 . + +use super::IntegerTester; + +test_int!(TestI128); + +#[test] +fn test_i128_min() { + TestI128::test_min(); +} + +#[test] +fn test_i128_max() { + TestI128::test_max(); +} + +#[test] +fn test_i128_neg() { + TestI128::test_negate(); +} + +#[test] +fn test_i128_neg_zero() { + TestI128::test_negate_zero(); +} + +#[test] +fn test_i128_add() { + TestI128::test_add(); +} + +#[test] +fn test_i128_sub() { + TestI128::test_sub(); +} + +#[test] +fn test_i128_mul() { + TestI128::test_mul(); +} + +#[test] +#[ignore] // takes several minutes +fn test_i128_div() { + TestI128::test_div(); +} + +#[test] +fn test_i128_pow() { + TestI128::test_pow(); +} + +#[test] +fn test_i128_eq() { + TestI128::test_eq(); +} + +#[test] +fn test_i128_ne() { + TestI128::test_ne(); +} + +#[test] +fn test_i128_ge() { + TestI128::test_ge(); +} + +#[test] +fn test_i128_gt() { + TestI128::test_gt(); +} + +#[test] +fn test_i128_le() { + TestI128::test_le(); +} + +#[test] +fn test_i128_lt() { + TestI128::test_lt(); +} + +#[test] +fn test_i128_assert_eq() { + TestI128::test_console_assert(); +} + +#[test] +fn test_i128_ternary() { + TestI128::test_ternary(); +} diff --git a/asg/tests/pass/integers/i128/mul.leo b/asg/tests/pass/integers/i128/mul.leo new file mode 100644 index 0000000000..25b902d53c --- /dev/null +++ b/asg/tests/pass/integers/i128/mul.leo @@ -0,0 +1,3 @@ +function main(a: i128, b: i128, c: i128) { + console.assert(a * b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i128/ne.leo b/asg/tests/pass/integers/i128/ne.leo new file mode 100644 index 0000000000..dae148b49c --- /dev/null +++ b/asg/tests/pass/integers/i128/ne.leo @@ -0,0 +1,3 @@ +function main(a: i128, b: i128, c: bool) { + console.assert(a != b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i128/negate.leo b/asg/tests/pass/integers/i128/negate.leo new file mode 100644 index 0000000000..437ee06390 --- /dev/null +++ b/asg/tests/pass/integers/i128/negate.leo @@ -0,0 +1,3 @@ +function main(a: i128, b: i128) { + console.assert(-a == b); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i128/negate_zero.leo b/asg/tests/pass/integers/i128/negate_zero.leo new file mode 100644 index 0000000000..9fb0c11afe --- /dev/null +++ b/asg/tests/pass/integers/i128/negate_zero.leo @@ -0,0 +1,5 @@ +function main() { + let a = 0i128; + + console.assert(-a == 0i128); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i128/pow.leo b/asg/tests/pass/integers/i128/pow.leo new file mode 100644 index 0000000000..05536aad51 --- /dev/null +++ b/asg/tests/pass/integers/i128/pow.leo @@ -0,0 +1,3 @@ +function main(a: i128, b: i128, c: i128) { + console.assert(a ** b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i128/sub.leo b/asg/tests/pass/integers/i128/sub.leo new file mode 100644 index 0000000000..3a723eec49 --- /dev/null +++ b/asg/tests/pass/integers/i128/sub.leo @@ -0,0 +1,3 @@ +function main(a: i128, b: i128, c: i128) { + console.assert(a - b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i128/ternary.leo b/asg/tests/pass/integers/i128/ternary.leo new file mode 100644 index 0000000000..5c2f199499 --- /dev/null +++ b/asg/tests/pass/integers/i128/ternary.leo @@ -0,0 +1,5 @@ +function main(s: bool, a: i128, b: i128, c: i128) { + let r = if s ? a : b; + + console.assert(r == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i16/add.leo b/asg/tests/pass/integers/i16/add.leo new file mode 100644 index 0000000000..556ae65c3a --- /dev/null +++ b/asg/tests/pass/integers/i16/add.leo @@ -0,0 +1,3 @@ +function main(a: i16, b: i16, c: i16) { + console.assert(a + b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i16/console_assert.leo b/asg/tests/pass/integers/i16/console_assert.leo new file mode 100644 index 0000000000..3afb25b207 --- /dev/null +++ b/asg/tests/pass/integers/i16/console_assert.leo @@ -0,0 +1,3 @@ +function main(a: i16, b: i16) { + console.assert(a == b); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i16/div.leo b/asg/tests/pass/integers/i16/div.leo new file mode 100644 index 0000000000..6d0c8f4614 --- /dev/null +++ b/asg/tests/pass/integers/i16/div.leo @@ -0,0 +1,3 @@ +function main(a: i16, b: i16, c: i16) { + console.assert(a / b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i16/eq.leo b/asg/tests/pass/integers/i16/eq.leo new file mode 100644 index 0000000000..338e3e50f6 --- /dev/null +++ b/asg/tests/pass/integers/i16/eq.leo @@ -0,0 +1,3 @@ +function main(a: i16, b: i16, c: bool) { + console.assert(a == b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i16/ge.leo b/asg/tests/pass/integers/i16/ge.leo new file mode 100644 index 0000000000..68a4d40bf8 --- /dev/null +++ b/asg/tests/pass/integers/i16/ge.leo @@ -0,0 +1,3 @@ +function main(a: i16, b: i16, c: bool) { + console.assert(a >= b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i16/gt.leo b/asg/tests/pass/integers/i16/gt.leo new file mode 100644 index 0000000000..75d9bfb612 --- /dev/null +++ b/asg/tests/pass/integers/i16/gt.leo @@ -0,0 +1,3 @@ +function main(a: i16, b: i16, c: bool) { + console.assert(a > b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i16/input.leo b/asg/tests/pass/integers/i16/input.leo new file mode 100644 index 0000000000..3afb25b207 --- /dev/null +++ b/asg/tests/pass/integers/i16/input.leo @@ -0,0 +1,3 @@ +function main(a: i16, b: i16) { + console.assert(a == b); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i16/le.leo b/asg/tests/pass/integers/i16/le.leo new file mode 100644 index 0000000000..ff112c7fbc --- /dev/null +++ b/asg/tests/pass/integers/i16/le.leo @@ -0,0 +1,3 @@ +function main(a: i16, b: i16, c: bool) { + console.assert(a <= b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i16/lt.leo b/asg/tests/pass/integers/i16/lt.leo new file mode 100644 index 0000000000..46c57aabe6 --- /dev/null +++ b/asg/tests/pass/integers/i16/lt.leo @@ -0,0 +1,3 @@ +function main(a: i16, b: i16, c: bool) { + console.assert(a < b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i16/max.leo b/asg/tests/pass/integers/i16/max.leo new file mode 100644 index 0000000000..084fe4969a --- /dev/null +++ b/asg/tests/pass/integers/i16/max.leo @@ -0,0 +1,3 @@ +function main() { + let a: i16 = 32767; +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i16/min.leo b/asg/tests/pass/integers/i16/min.leo new file mode 100644 index 0000000000..3331281fcf --- /dev/null +++ b/asg/tests/pass/integers/i16/min.leo @@ -0,0 +1,3 @@ +function main() { + let a: i16 = -32768; +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i16/mod.rs b/asg/tests/pass/integers/i16/mod.rs new file mode 100644 index 0000000000..e5a329d18a --- /dev/null +++ b/asg/tests/pass/integers/i16/mod.rs @@ -0,0 +1,120 @@ +// 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 . + +// 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 . + +use super::IntegerTester; + +test_int!(TestI16); + +#[test] +fn test_i16_min() { + TestI16::test_min(); +} + +#[test] +fn test_i16_max() { + TestI16::test_max(); +} + +#[test] +fn test_i16_neg() { + TestI16::test_negate(); +} + +#[test] +fn test_i16_neg_zero() { + TestI16::test_negate_zero(); +} + +#[test] +fn test_i16_add() { + TestI16::test_add(); +} + +#[test] +fn test_i16_sub() { + TestI16::test_sub(); +} + +#[test] +fn test_i16_mul() { + TestI16::test_mul(); +} + +#[test] +fn test_i16_div() { + TestI16::test_div(); +} + +#[test] +fn test_i16_pow() { + TestI16::test_pow(); +} + +#[test] +fn test_i16_eq() { + TestI16::test_eq(); +} + +#[test] +fn test_i16_ne() { + TestI16::test_ne(); +} + +#[test] +fn test_i16_ge() { + TestI16::test_ge(); +} + +#[test] +fn test_i16_gt() { + TestI16::test_gt(); +} + +#[test] +fn test_i16_le() { + TestI16::test_le(); +} + +#[test] +fn test_i16_lt() { + TestI16::test_lt(); +} + +#[test] +fn test_i16_console_assert() { + TestI16::test_console_assert(); +} + +#[test] +fn test_i16_ternary() { + TestI16::test_ternary(); +} diff --git a/asg/tests/pass/integers/i16/mul.leo b/asg/tests/pass/integers/i16/mul.leo new file mode 100644 index 0000000000..6fd19b703a --- /dev/null +++ b/asg/tests/pass/integers/i16/mul.leo @@ -0,0 +1,3 @@ +function main(a: i16, b: i16, c: i16) { + console.assert(a * b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i16/ne.leo b/asg/tests/pass/integers/i16/ne.leo new file mode 100644 index 0000000000..f0a9472678 --- /dev/null +++ b/asg/tests/pass/integers/i16/ne.leo @@ -0,0 +1,3 @@ +function main(a: i16, b: i16, c: bool) { + console.assert(a != b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i16/negate.leo b/asg/tests/pass/integers/i16/negate.leo new file mode 100644 index 0000000000..1d2644dce7 --- /dev/null +++ b/asg/tests/pass/integers/i16/negate.leo @@ -0,0 +1,3 @@ +function main(a: i16, b: i16) { + console.assert(-a == b); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i16/negate_zero.leo b/asg/tests/pass/integers/i16/negate_zero.leo new file mode 100644 index 0000000000..46340c3dc5 --- /dev/null +++ b/asg/tests/pass/integers/i16/negate_zero.leo @@ -0,0 +1,5 @@ +function main() { + let a = 0i16; + + console.assert(-a == 0i16); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i16/pow.leo b/asg/tests/pass/integers/i16/pow.leo new file mode 100644 index 0000000000..769d2d2fbb --- /dev/null +++ b/asg/tests/pass/integers/i16/pow.leo @@ -0,0 +1,3 @@ +function main(a: i16, b: i16, c: i16) { + console.assert(a ** b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i16/sub.leo b/asg/tests/pass/integers/i16/sub.leo new file mode 100644 index 0000000000..e935935187 --- /dev/null +++ b/asg/tests/pass/integers/i16/sub.leo @@ -0,0 +1,3 @@ +function main(a: i16, b: i16, c: i16) { + console.assert(a - b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i16/ternary.leo b/asg/tests/pass/integers/i16/ternary.leo new file mode 100644 index 0000000000..ccf29bfd50 --- /dev/null +++ b/asg/tests/pass/integers/i16/ternary.leo @@ -0,0 +1,5 @@ +function main(s: bool, a: i16, b: i16, c: i16) { + let r = if s ? a : b; + + console.assert(r == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i32/add.leo b/asg/tests/pass/integers/i32/add.leo new file mode 100644 index 0000000000..3d8fb1b1d2 --- /dev/null +++ b/asg/tests/pass/integers/i32/add.leo @@ -0,0 +1,3 @@ +function main(a: i32, b: i32, c: i32) { + console.assert(a + b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i32/console_assert.leo b/asg/tests/pass/integers/i32/console_assert.leo new file mode 100644 index 0000000000..a2d6980e9a --- /dev/null +++ b/asg/tests/pass/integers/i32/console_assert.leo @@ -0,0 +1,3 @@ +function main(a: i32, b: i32) { + console.assert(a == b); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i32/div.leo b/asg/tests/pass/integers/i32/div.leo new file mode 100644 index 0000000000..3189a354f0 --- /dev/null +++ b/asg/tests/pass/integers/i32/div.leo @@ -0,0 +1,3 @@ +function main(a: i32, b: i32, c: i32) { + console.assert(a / b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i32/eq.leo b/asg/tests/pass/integers/i32/eq.leo new file mode 100644 index 0000000000..bac7af0be0 --- /dev/null +++ b/asg/tests/pass/integers/i32/eq.leo @@ -0,0 +1,3 @@ +function main(a: i32, b: i32, c: bool) { + console.assert(a == b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i32/ge.leo b/asg/tests/pass/integers/i32/ge.leo new file mode 100644 index 0000000000..362521fc82 --- /dev/null +++ b/asg/tests/pass/integers/i32/ge.leo @@ -0,0 +1,3 @@ +function main(a: i32, b: i32, c: bool) { + console.assert(a >= b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i32/gt.leo b/asg/tests/pass/integers/i32/gt.leo new file mode 100644 index 0000000000..63ddcaa85c --- /dev/null +++ b/asg/tests/pass/integers/i32/gt.leo @@ -0,0 +1,3 @@ +function main(a: i32, b: i32, c: bool) { + console.assert(a > b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i32/input.leo b/asg/tests/pass/integers/i32/input.leo new file mode 100644 index 0000000000..a2d6980e9a --- /dev/null +++ b/asg/tests/pass/integers/i32/input.leo @@ -0,0 +1,3 @@ +function main(a: i32, b: i32) { + console.assert(a == b); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i32/le.leo b/asg/tests/pass/integers/i32/le.leo new file mode 100644 index 0000000000..948c66b1fc --- /dev/null +++ b/asg/tests/pass/integers/i32/le.leo @@ -0,0 +1,3 @@ +function main(a: i32, b: i32, c: bool) { + console.assert(a <= b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i32/lt.leo b/asg/tests/pass/integers/i32/lt.leo new file mode 100644 index 0000000000..72a8fb0d53 --- /dev/null +++ b/asg/tests/pass/integers/i32/lt.leo @@ -0,0 +1,3 @@ +function main(a: i32, b: i32, c: bool) { + console.assert(a < b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i32/max.leo b/asg/tests/pass/integers/i32/max.leo new file mode 100644 index 0000000000..a9c707eb7f --- /dev/null +++ b/asg/tests/pass/integers/i32/max.leo @@ -0,0 +1,3 @@ +function main() { + let a: i32 = 2147483647; +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i32/min.leo b/asg/tests/pass/integers/i32/min.leo new file mode 100644 index 0000000000..a29d591029 --- /dev/null +++ b/asg/tests/pass/integers/i32/min.leo @@ -0,0 +1,3 @@ +function main() { + let a: i32 = -2147483648; +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i32/mod.rs b/asg/tests/pass/integers/i32/mod.rs new file mode 100644 index 0000000000..a2f1012941 --- /dev/null +++ b/asg/tests/pass/integers/i32/mod.rs @@ -0,0 +1,120 @@ +// 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 . + +// 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 . + +use super::IntegerTester; + +test_int!(TestI32); + +#[test] +fn test_i32_min() { + TestI32::test_min(); +} + +#[test] +fn test_i32_max() { + TestI32::test_max(); +} + +#[test] +fn test_i32_neg() { + TestI32::test_negate(); +} + +#[test] +fn test_i32_neg_zero() { + TestI32::test_negate_zero(); +} + +#[test] +fn test_i32_add() { + TestI32::test_add(); +} + +#[test] +fn test_i32_sub() { + TestI32::test_sub(); +} + +#[test] +fn test_i32_mul() { + TestI32::test_mul(); +} + +#[test] +fn test_i32_div() { + TestI32::test_div(); +} + +#[test] +fn test_i32_pow() { + TestI32::test_pow(); +} + +#[test] +fn test_i32_eq() { + TestI32::test_eq(); +} + +#[test] +fn test_i32_ne() { + TestI32::test_ne(); +} + +#[test] +fn test_i32_ge() { + TestI32::test_ge(); +} + +#[test] +fn test_i32_gt() { + TestI32::test_gt(); +} + +#[test] +fn test_i32_le() { + TestI32::test_le(); +} + +#[test] +fn test_i32_lt() { + TestI32::test_lt(); +} + +#[test] +fn test_i32_console_assert() { + TestI32::test_console_assert(); +} + +#[test] +fn test_i32_ternary() { + TestI32::test_ternary(); +} diff --git a/asg/tests/pass/integers/i32/mul.leo b/asg/tests/pass/integers/i32/mul.leo new file mode 100644 index 0000000000..50ba5b4128 --- /dev/null +++ b/asg/tests/pass/integers/i32/mul.leo @@ -0,0 +1,3 @@ +function main(a: i32, b: i32, c: i32) { + console.assert(a * b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i32/ne.leo b/asg/tests/pass/integers/i32/ne.leo new file mode 100644 index 0000000000..dcc1a185d1 --- /dev/null +++ b/asg/tests/pass/integers/i32/ne.leo @@ -0,0 +1,3 @@ +function main(a: i32, b: i32, c: bool) { + console.assert(a != b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i32/negate.leo b/asg/tests/pass/integers/i32/negate.leo new file mode 100644 index 0000000000..eef94c934f --- /dev/null +++ b/asg/tests/pass/integers/i32/negate.leo @@ -0,0 +1,3 @@ +function main(a: i32, b: i32) { + console.assert(-a == b); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i32/negate_zero.leo b/asg/tests/pass/integers/i32/negate_zero.leo new file mode 100644 index 0000000000..5533f575a6 --- /dev/null +++ b/asg/tests/pass/integers/i32/negate_zero.leo @@ -0,0 +1,5 @@ +function main() { + let a = 0i32; + + console.assert(-a == 0i32); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i32/pow.leo b/asg/tests/pass/integers/i32/pow.leo new file mode 100644 index 0000000000..ebb131e30b --- /dev/null +++ b/asg/tests/pass/integers/i32/pow.leo @@ -0,0 +1,3 @@ +function main(a: i32, b: i32, c: i32) { + console.assert(a ** b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i32/sub.leo b/asg/tests/pass/integers/i32/sub.leo new file mode 100644 index 0000000000..1f054a5ddf --- /dev/null +++ b/asg/tests/pass/integers/i32/sub.leo @@ -0,0 +1,3 @@ +function main(a: i32, b: i32, c: i32) { + console.assert(a - b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i32/ternary.leo b/asg/tests/pass/integers/i32/ternary.leo new file mode 100644 index 0000000000..3066547ae3 --- /dev/null +++ b/asg/tests/pass/integers/i32/ternary.leo @@ -0,0 +1,5 @@ +function main(s: bool, a: i32, b: i32, c: i32) { + let r = if s ? a : b; + + console.assert(r == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i64/add.leo b/asg/tests/pass/integers/i64/add.leo new file mode 100644 index 0000000000..aefdbb178f --- /dev/null +++ b/asg/tests/pass/integers/i64/add.leo @@ -0,0 +1,3 @@ +function main(a: i64, b: i64, c: i64) { + console.assert(a + b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i64/console_assert.leo b/asg/tests/pass/integers/i64/console_assert.leo new file mode 100644 index 0000000000..ab9a5d6e91 --- /dev/null +++ b/asg/tests/pass/integers/i64/console_assert.leo @@ -0,0 +1,3 @@ +function main(a: i64, b: i64) { + console.assert(a == b); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i64/div.leo b/asg/tests/pass/integers/i64/div.leo new file mode 100644 index 0000000000..142e4ab801 --- /dev/null +++ b/asg/tests/pass/integers/i64/div.leo @@ -0,0 +1,3 @@ +function main(a: i64, b: i64, c: i64) { + console.assert(a / b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i64/eq.leo b/asg/tests/pass/integers/i64/eq.leo new file mode 100644 index 0000000000..86a234c834 --- /dev/null +++ b/asg/tests/pass/integers/i64/eq.leo @@ -0,0 +1,3 @@ +function main(a: i64, b: i64, c: bool) { + console.assert(a == b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i64/ge.leo b/asg/tests/pass/integers/i64/ge.leo new file mode 100644 index 0000000000..e7b453c5dc --- /dev/null +++ b/asg/tests/pass/integers/i64/ge.leo @@ -0,0 +1,3 @@ +function main(a: i64, b: i64, c: bool) { + console.assert(a >= b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i64/gt.leo b/asg/tests/pass/integers/i64/gt.leo new file mode 100644 index 0000000000..9709bad012 --- /dev/null +++ b/asg/tests/pass/integers/i64/gt.leo @@ -0,0 +1,3 @@ +function main(a: i64, b: i64, c: bool) { + console.assert(a > b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i64/input.leo b/asg/tests/pass/integers/i64/input.leo new file mode 100644 index 0000000000..ab9a5d6e91 --- /dev/null +++ b/asg/tests/pass/integers/i64/input.leo @@ -0,0 +1,3 @@ +function main(a: i64, b: i64) { + console.assert(a == b); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i64/le.leo b/asg/tests/pass/integers/i64/le.leo new file mode 100644 index 0000000000..3e2cfcb711 --- /dev/null +++ b/asg/tests/pass/integers/i64/le.leo @@ -0,0 +1,3 @@ +function main(a: i64, b: i64, c: bool) { + console.assert(a <= b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i64/lt.leo b/asg/tests/pass/integers/i64/lt.leo new file mode 100644 index 0000000000..ef4e38eb76 --- /dev/null +++ b/asg/tests/pass/integers/i64/lt.leo @@ -0,0 +1,3 @@ +function main(a: i64, b: i64, c: bool) { + console.assert(a < b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i64/max.leo b/asg/tests/pass/integers/i64/max.leo new file mode 100644 index 0000000000..e0d19881e6 --- /dev/null +++ b/asg/tests/pass/integers/i64/max.leo @@ -0,0 +1,3 @@ +function main() { + let a: i64 = 9223372036854775807; +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i64/min.leo b/asg/tests/pass/integers/i64/min.leo new file mode 100644 index 0000000000..d7e99a87f8 --- /dev/null +++ b/asg/tests/pass/integers/i64/min.leo @@ -0,0 +1,3 @@ +function main() { + let a: i64 = -9223372036854775808; +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i64/mod.rs b/asg/tests/pass/integers/i64/mod.rs new file mode 100644 index 0000000000..e4cce13da3 --- /dev/null +++ b/asg/tests/pass/integers/i64/mod.rs @@ -0,0 +1,121 @@ +// 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 . + +// 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 . + +use super::IntegerTester; + +test_int!(TestI64); + +#[test] +fn test_i64_min() { + TestI64::test_min(); +} + +#[test] +fn test_i64_max() { + TestI64::test_max(); +} + +#[test] +fn test_i64_neg() { + TestI64::test_negate(); +} + +#[test] +fn test_i64_neg_zero() { + TestI64::test_negate_zero(); +} + +#[test] +fn test_i64_add() { + TestI64::test_add(); +} + +#[test] +fn test_i64_sub() { + TestI64::test_sub(); +} + +#[test] +fn test_i64_mul() { + TestI64::test_mul(); +} + +#[test] +#[ignore] // takes 2 minutes +fn test_i64_div() { + TestI64::test_div(); +} + +#[test] +fn test_i64_pow() { + TestI64::test_pow(); +} + +#[test] +fn test_i64_eq() { + TestI64::test_eq(); +} + +#[test] +fn test_i64_ne() { + TestI64::test_ne(); +} + +#[test] +fn test_i64_ge() { + TestI64::test_ge(); +} + +#[test] +fn test_i64_gt() { + TestI64::test_gt(); +} + +#[test] +fn test_i64_le() { + TestI64::test_le(); +} + +#[test] +fn test_i64_lt() { + TestI64::test_lt(); +} + +#[test] +fn test_i64_console_assert() { + TestI64::test_console_assert(); +} + +#[test] +fn test_i64_ternary() { + TestI64::test_ternary(); +} diff --git a/asg/tests/pass/integers/i64/mul.leo b/asg/tests/pass/integers/i64/mul.leo new file mode 100644 index 0000000000..a3b8bd1da5 --- /dev/null +++ b/asg/tests/pass/integers/i64/mul.leo @@ -0,0 +1,3 @@ +function main(a: i64, b: i64, c: i64) { + console.assert(a * b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i64/ne.leo b/asg/tests/pass/integers/i64/ne.leo new file mode 100644 index 0000000000..a2642bb479 --- /dev/null +++ b/asg/tests/pass/integers/i64/ne.leo @@ -0,0 +1,3 @@ +function main(a: i64, b: i64, c: bool) { + console.assert(a != b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i64/negate.leo b/asg/tests/pass/integers/i64/negate.leo new file mode 100644 index 0000000000..fe0cdc4d97 --- /dev/null +++ b/asg/tests/pass/integers/i64/negate.leo @@ -0,0 +1,3 @@ +function main(a: i64, b: i64) { + console.assert(-a == b); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i64/negate_zero.leo b/asg/tests/pass/integers/i64/negate_zero.leo new file mode 100644 index 0000000000..6badfe4dc7 --- /dev/null +++ b/asg/tests/pass/integers/i64/negate_zero.leo @@ -0,0 +1,5 @@ +function main() { + let a = 0i64; + + console.assert(-a == 0i64); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i64/pow.leo b/asg/tests/pass/integers/i64/pow.leo new file mode 100644 index 0000000000..dca2dace74 --- /dev/null +++ b/asg/tests/pass/integers/i64/pow.leo @@ -0,0 +1,3 @@ +function main(a: i64, b: i64, c: i64) { + console.assert(a ** b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i64/sub.leo b/asg/tests/pass/integers/i64/sub.leo new file mode 100644 index 0000000000..4d335e504b --- /dev/null +++ b/asg/tests/pass/integers/i64/sub.leo @@ -0,0 +1,3 @@ +function main(a: i64, b: i64, c: i64) { + console.assert(a - b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i64/ternary.leo b/asg/tests/pass/integers/i64/ternary.leo new file mode 100644 index 0000000000..811c759bdf --- /dev/null +++ b/asg/tests/pass/integers/i64/ternary.leo @@ -0,0 +1,5 @@ +function main(s: bool, a: i64, b: i64, c: i64) { + let r = if s ? a : b; + + console.assert(r == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i8/add.leo b/asg/tests/pass/integers/i8/add.leo new file mode 100644 index 0000000000..dd71bc7f53 --- /dev/null +++ b/asg/tests/pass/integers/i8/add.leo @@ -0,0 +1,3 @@ +function main(a: i8, b: i8, c: i8) { + console.assert(a + b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i8/console_assert.leo b/asg/tests/pass/integers/i8/console_assert.leo new file mode 100644 index 0000000000..1fc09cb57d --- /dev/null +++ b/asg/tests/pass/integers/i8/console_assert.leo @@ -0,0 +1,3 @@ +function main(a: i8, b: i8) { + console.assert(a == b); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i8/div.leo b/asg/tests/pass/integers/i8/div.leo new file mode 100644 index 0000000000..a80d8e6319 --- /dev/null +++ b/asg/tests/pass/integers/i8/div.leo @@ -0,0 +1,3 @@ +function main(a: i8, b: i8, c: i8) { + console.assert(a / b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i8/eq.leo b/asg/tests/pass/integers/i8/eq.leo new file mode 100644 index 0000000000..130cc64b89 --- /dev/null +++ b/asg/tests/pass/integers/i8/eq.leo @@ -0,0 +1,3 @@ +function main(a: i8, b: i8, c: bool) { + console.assert(a == b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i8/ge.leo b/asg/tests/pass/integers/i8/ge.leo new file mode 100644 index 0000000000..3084692c0c --- /dev/null +++ b/asg/tests/pass/integers/i8/ge.leo @@ -0,0 +1,3 @@ +function main(a: i8, b: i8, c: bool) { + console.assert(a >= b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i8/gt.leo b/asg/tests/pass/integers/i8/gt.leo new file mode 100644 index 0000000000..d3913b8b24 --- /dev/null +++ b/asg/tests/pass/integers/i8/gt.leo @@ -0,0 +1,3 @@ +function main(a: i8, b: i8, c: bool) { + console.assert(a > b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i8/input.leo b/asg/tests/pass/integers/i8/input.leo new file mode 100644 index 0000000000..1fc09cb57d --- /dev/null +++ b/asg/tests/pass/integers/i8/input.leo @@ -0,0 +1,3 @@ +function main(a: i8, b: i8) { + console.assert(a == b); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i8/le.leo b/asg/tests/pass/integers/i8/le.leo new file mode 100644 index 0000000000..92e011f206 --- /dev/null +++ b/asg/tests/pass/integers/i8/le.leo @@ -0,0 +1,3 @@ +function main(a: i8, b: i8, c: bool) { + console.assert(a <= b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i8/lt.leo b/asg/tests/pass/integers/i8/lt.leo new file mode 100644 index 0000000000..eb34b7148e --- /dev/null +++ b/asg/tests/pass/integers/i8/lt.leo @@ -0,0 +1,3 @@ +function main(a: i8, b: i8, c: bool) { + console.assert(a < b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i8/max.leo b/asg/tests/pass/integers/i8/max.leo new file mode 100644 index 0000000000..b51126da59 --- /dev/null +++ b/asg/tests/pass/integers/i8/max.leo @@ -0,0 +1,3 @@ +function main() { + let a: i8 = 127; +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i8/min.leo b/asg/tests/pass/integers/i8/min.leo new file mode 100644 index 0000000000..d3c1bff5e4 --- /dev/null +++ b/asg/tests/pass/integers/i8/min.leo @@ -0,0 +1,3 @@ +function main() { + let a: i8 = -128; +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i8/mod.rs b/asg/tests/pass/integers/i8/mod.rs new file mode 100644 index 0000000000..225e7a3c55 --- /dev/null +++ b/asg/tests/pass/integers/i8/mod.rs @@ -0,0 +1,120 @@ +// 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 . + +// 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 . + +use super::IntegerTester; + +test_int!(TestI8); + +#[test] +fn test_i8_min() { + TestI8::test_min(); +} + +#[test] +fn test_i8_max() { + TestI8::test_max(); +} + +#[test] +fn test_i8_neg() { + TestI8::test_negate(); +} + +#[test] +fn test_i8_neg_zero() { + TestI8::test_negate_zero(); +} + +#[test] +fn test_i8_add() { + TestI8::test_add(); +} + +#[test] +fn test_i8_sub() { + TestI8::test_sub(); +} + +#[test] +fn test_i8_mul() { + TestI8::test_mul(); +} + +#[test] +fn test_i8_div() { + TestI8::test_div(); +} + +#[test] +fn test_i8_pow() { + TestI8::test_pow(); +} + +#[test] +fn test_i8_eq() { + TestI8::test_eq(); +} + +#[test] +fn test_i8_ne() { + TestI8::test_ne(); +} + +#[test] +fn test_i8_ge() { + TestI8::test_ge(); +} + +#[test] +fn test_i8_gt() { + TestI8::test_gt(); +} + +#[test] +fn test_i8_le() { + TestI8::test_le(); +} + +#[test] +fn test_i8_lt() { + TestI8::test_lt(); +} + +#[test] +fn test_i8_console_assert() { + TestI8::test_console_assert(); +} + +#[test] +fn test_i8_ternary() { + TestI8::test_ternary(); +} diff --git a/asg/tests/pass/integers/i8/mul.leo b/asg/tests/pass/integers/i8/mul.leo new file mode 100644 index 0000000000..34726fff92 --- /dev/null +++ b/asg/tests/pass/integers/i8/mul.leo @@ -0,0 +1,3 @@ +function main(a: i8, b: i8, c: i8) { + console.assert(a * b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i8/ne.leo b/asg/tests/pass/integers/i8/ne.leo new file mode 100644 index 0000000000..e5028d404a --- /dev/null +++ b/asg/tests/pass/integers/i8/ne.leo @@ -0,0 +1,3 @@ +function main(a: i8, b: i8, c: bool) { + console.assert(a != b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i8/negate.leo b/asg/tests/pass/integers/i8/negate.leo new file mode 100644 index 0000000000..2a2266bc56 --- /dev/null +++ b/asg/tests/pass/integers/i8/negate.leo @@ -0,0 +1,3 @@ +function main(a: i8, b: i8) { + console.assert(-a == b); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i8/negate_zero.leo b/asg/tests/pass/integers/i8/negate_zero.leo new file mode 100644 index 0000000000..21fbbab675 --- /dev/null +++ b/asg/tests/pass/integers/i8/negate_zero.leo @@ -0,0 +1,5 @@ +function main() { + let a = 0i8; + + console.assert(-a == 0i8); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i8/pow.leo b/asg/tests/pass/integers/i8/pow.leo new file mode 100644 index 0000000000..18aeb44b46 --- /dev/null +++ b/asg/tests/pass/integers/i8/pow.leo @@ -0,0 +1,3 @@ +function main(a: i8, b: i8, c: i8) { + console.assert(a ** b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i8/sub.leo b/asg/tests/pass/integers/i8/sub.leo new file mode 100644 index 0000000000..a795bed153 --- /dev/null +++ b/asg/tests/pass/integers/i8/sub.leo @@ -0,0 +1,3 @@ +function main(a: i8, b: i8, c: i8) { + console.assert(a - b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/i8/ternary.leo b/asg/tests/pass/integers/i8/ternary.leo new file mode 100644 index 0000000000..de797c6e3b --- /dev/null +++ b/asg/tests/pass/integers/i8/ternary.leo @@ -0,0 +1,5 @@ +function main(s: bool, a: i8, b: i8, c: i8) { + let r = if s ? a : b; + + console.assert(r == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/int_macro.rs b/asg/tests/pass/integers/int_macro.rs new file mode 100644 index 0000000000..734b1773e5 --- /dev/null +++ b/asg/tests/pass/integers/int_macro.rs @@ -0,0 +1,126 @@ +// 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 . + +// 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 . + +macro_rules! test_int { + ($name: ident) => { + pub struct $name {} + + impl $name { + fn test_negate() { + let program_string = include_str!("negate.leo"); + crate::load_asg(program_string).unwrap(); + } + + fn test_negate_zero() { + let program_string = include_str!("negate_zero.leo"); + crate::load_asg(program_string).unwrap(); + } + } + + impl super::IntegerTester for $name { + fn test_min() { + let program_string = include_str!("min.leo"); + crate::load_asg(program_string).unwrap(); + } + + fn test_max() { + let program_string = include_str!("max.leo"); + crate::load_asg(program_string).unwrap(); + } + + fn test_add() { + let program_string = include_str!("add.leo"); + crate::load_asg(program_string).unwrap(); + } + + fn test_sub() { + let program_string = include_str!("sub.leo"); + crate::load_asg(program_string).unwrap(); + } + + fn test_mul() { + let program_string = include_str!("mul.leo"); + crate::load_asg(program_string).unwrap(); + } + + fn test_div() { + let program_string = include_str!("div.leo"); + crate::load_asg(program_string).unwrap(); + } + + fn test_pow() { + let program_string = include_str!("pow.leo"); + crate::load_asg(program_string).unwrap(); + } + + fn test_eq() { + let program_string = include_str!("eq.leo"); + crate::load_asg(program_string).unwrap(); + } + + fn test_ne() { + let program_string = include_str!("ne.leo"); + crate::load_asg(program_string).unwrap(); + } + + fn test_ge() { + let program_string = include_str!("ge.leo"); + crate::load_asg(program_string).unwrap(); + } + + fn test_gt() { + let program_string = include_str!("gt.leo"); + crate::load_asg(program_string).unwrap(); + } + + fn test_le() { + let program_string = include_str!("le.leo"); + crate::load_asg(program_string).unwrap(); + } + + fn test_lt() { + let program_string = include_str!("lt.leo"); + crate::load_asg(program_string).unwrap(); + } + + fn test_console_assert() { + let program_string = include_str!("console_assert.leo"); + crate::load_asg(program_string).unwrap(); + } + + fn test_ternary() { + let program_string = include_str!("ternary.leo"); + crate::load_asg(program_string).unwrap(); + } + } + }; +} diff --git a/asg/tests/pass/integers/integer_tester.rs b/asg/tests/pass/integers/integer_tester.rs new file mode 100644 index 0000000000..f72930b8d0 --- /dev/null +++ b/asg/tests/pass/integers/integer_tester.rs @@ -0,0 +1,78 @@ +// 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 . + +// 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 . + +pub trait IntegerTester { + /// Tests defining the smalled value that can be represented by the integer type + fn test_min(); + + /// Tests defining the largest value that can be represented by the integer type + fn test_max(); + + /// Tests a non-wrapping addition + fn test_add(); + + /// Tests a non-wrapping subtraction + fn test_sub(); + + /// Tests a non-wrapping multiplication + fn test_mul(); + + /// Tests a non-wrapping division + fn test_div(); + + /// Tests a non-wrapping exponentiation + fn test_pow(); + + /// Tests == evaluation + fn test_eq(); + + /// Tests != evaluation + fn test_ne(); + + /// Tests >= evaluation + fn test_ge(); + + /// Tests > evaluation + fn test_gt(); + + /// Tests <= evaluation + fn test_le(); + + /// Tests < evaluation + fn test_lt(); + + /// Test assert equals constraint keyword + fn test_console_assert(); + + /// Test ternary if bool ? num_1 : num_2; + fn test_ternary(); +} diff --git a/asg/tests/pass/integers/mod.rs b/asg/tests/pass/integers/mod.rs new file mode 100644 index 0000000000..d9fc896497 --- /dev/null +++ b/asg/tests/pass/integers/mod.rs @@ -0,0 +1,53 @@ +// 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 . + +// 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 . + +#[macro_use] +pub mod int_macro; + +#[macro_use] +pub mod uint_macro; + +pub mod integer_tester; +pub use self::integer_tester::*; + +// must be below macro definitions! +pub mod u128; +pub mod u16; +pub mod u32; +pub mod u64; +pub mod u8; + +pub mod i128; +pub mod i16; +pub mod i32; +pub mod i64; +pub mod i8; diff --git a/asg/tests/pass/integers/u128/add.leo b/asg/tests/pass/integers/u128/add.leo new file mode 100644 index 0000000000..6b32042fd5 --- /dev/null +++ b/asg/tests/pass/integers/u128/add.leo @@ -0,0 +1,3 @@ +function main(a: u128, b: u128, c: u128) { + console.assert(a + b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u128/console_assert.leo b/asg/tests/pass/integers/u128/console_assert.leo new file mode 100644 index 0000000000..adab295385 --- /dev/null +++ b/asg/tests/pass/integers/u128/console_assert.leo @@ -0,0 +1,3 @@ +function main(a: u128, b: u128) { + console.assert(a == b); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u128/div.leo b/asg/tests/pass/integers/u128/div.leo new file mode 100644 index 0000000000..0d62054eca --- /dev/null +++ b/asg/tests/pass/integers/u128/div.leo @@ -0,0 +1,3 @@ +function main(a: u128, b: u128, c: u128) { + console.assert(a / b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u128/eq.leo b/asg/tests/pass/integers/u128/eq.leo new file mode 100644 index 0000000000..2c2acd923a --- /dev/null +++ b/asg/tests/pass/integers/u128/eq.leo @@ -0,0 +1,3 @@ +function main(a: u128, b: u128, c: bool) { + console.assert(a == b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u128/ge.leo b/asg/tests/pass/integers/u128/ge.leo new file mode 100644 index 0000000000..bff7cd321b --- /dev/null +++ b/asg/tests/pass/integers/u128/ge.leo @@ -0,0 +1,3 @@ +function main(a: u128, b: u128, c: bool) { + console.assert(a >= b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u128/gt.leo b/asg/tests/pass/integers/u128/gt.leo new file mode 100644 index 0000000000..e8aec0faf2 --- /dev/null +++ b/asg/tests/pass/integers/u128/gt.leo @@ -0,0 +1,3 @@ +function main(a: u128, b: u128, c: bool) { + console.assert(a > b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u128/input.leo b/asg/tests/pass/integers/u128/input.leo new file mode 100644 index 0000000000..adab295385 --- /dev/null +++ b/asg/tests/pass/integers/u128/input.leo @@ -0,0 +1,3 @@ +function main(a: u128, b: u128) { + console.assert(a == b); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u128/le.leo b/asg/tests/pass/integers/u128/le.leo new file mode 100644 index 0000000000..c9e4609136 --- /dev/null +++ b/asg/tests/pass/integers/u128/le.leo @@ -0,0 +1,3 @@ +function main(a: u128, b: u128, c: bool) { + console.assert(a <= b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u128/lt.leo b/asg/tests/pass/integers/u128/lt.leo new file mode 100644 index 0000000000..b37057c895 --- /dev/null +++ b/asg/tests/pass/integers/u128/lt.leo @@ -0,0 +1,3 @@ +function main(a: u128, b: u128, c: bool) { + console.assert(a < b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u128/max.leo b/asg/tests/pass/integers/u128/max.leo new file mode 100644 index 0000000000..6da59dd058 --- /dev/null +++ b/asg/tests/pass/integers/u128/max.leo @@ -0,0 +1,3 @@ +function main() { + let a: u128 = 340282366920938463463374607431768211455; +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u128/min.leo b/asg/tests/pass/integers/u128/min.leo new file mode 100644 index 0000000000..044bda9e1c --- /dev/null +++ b/asg/tests/pass/integers/u128/min.leo @@ -0,0 +1,3 @@ +function main() { + let a: u128 = 0; +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u128/mod.rs b/asg/tests/pass/integers/u128/mod.rs new file mode 100644 index 0000000000..f025e85ba5 --- /dev/null +++ b/asg/tests/pass/integers/u128/mod.rs @@ -0,0 +1,110 @@ +// 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 . + +// 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 . + +use super::IntegerTester; + +test_uint!(TestU128); + +#[test] +fn test_u128_min() { + TestU128::test_min(); +} + +#[test] +fn test_u128_max() { + TestU128::test_max(); +} + +#[test] +fn test_u128_add() { + TestU128::test_add(); +} + +#[test] +fn test_u128_sub() { + TestU128::test_sub(); +} + +#[test] +fn test_u128_mul() { + TestU128::test_mul(); +} + +#[test] +fn test_u128_div() { + TestU128::test_div(); +} + +#[test] +fn test_u128_pow() { + TestU128::test_pow(); +} + +#[test] +fn test_u128_eq() { + TestU128::test_eq(); +} + +#[test] +fn test_u128_ne() { + TestU128::test_ne(); +} + +#[test] +fn test_u128_ge() { + TestU128::test_ge(); +} + +#[test] +fn test_u128_gt() { + TestU128::test_gt(); +} + +#[test] +fn test_u128_le() { + TestU128::test_le(); +} + +#[test] +fn test_u128_lt() { + TestU128::test_lt(); +} + +#[test] +fn test_u128_console_assert() { + TestU128::test_console_assert(); +} + +#[test] +fn test_u128_ternary() { + TestU128::test_ternary(); +} diff --git a/asg/tests/pass/integers/u128/mul.leo b/asg/tests/pass/integers/u128/mul.leo new file mode 100644 index 0000000000..c7fdc1530c --- /dev/null +++ b/asg/tests/pass/integers/u128/mul.leo @@ -0,0 +1,3 @@ +function main(a: u128, b: u128, c: u128) { + console.assert(a * b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u128/ne.leo b/asg/tests/pass/integers/u128/ne.leo new file mode 100644 index 0000000000..da3467d01e --- /dev/null +++ b/asg/tests/pass/integers/u128/ne.leo @@ -0,0 +1,3 @@ +function main(a: u128, b: u128, c: bool) { + console.assert(a != b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u128/pow.leo b/asg/tests/pass/integers/u128/pow.leo new file mode 100644 index 0000000000..27614bfa56 --- /dev/null +++ b/asg/tests/pass/integers/u128/pow.leo @@ -0,0 +1,3 @@ +function main(a: u128, b: u128, c: u128) { + console.assert(a ** b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u128/sub.leo b/asg/tests/pass/integers/u128/sub.leo new file mode 100644 index 0000000000..2374413505 --- /dev/null +++ b/asg/tests/pass/integers/u128/sub.leo @@ -0,0 +1,3 @@ +function main(a: u128, b: u128, c: u128) { + console.assert(a - b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u128/ternary.leo b/asg/tests/pass/integers/u128/ternary.leo new file mode 100644 index 0000000000..48299fac66 --- /dev/null +++ b/asg/tests/pass/integers/u128/ternary.leo @@ -0,0 +1,5 @@ +function main(s: bool, a: u128, b: u128, c: u128) { + let r = if s ? a : b; + + console.assert(r == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u16/add.leo b/asg/tests/pass/integers/u16/add.leo new file mode 100644 index 0000000000..f00701181b --- /dev/null +++ b/asg/tests/pass/integers/u16/add.leo @@ -0,0 +1,3 @@ +function main(a: u16, b: u16, c: u16) { + console.assert(a + b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u16/console_assert.leo b/asg/tests/pass/integers/u16/console_assert.leo new file mode 100644 index 0000000000..761f0639d0 --- /dev/null +++ b/asg/tests/pass/integers/u16/console_assert.leo @@ -0,0 +1,3 @@ +function main(a: u16, b: u16) { + console.assert(a == b); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u16/div.leo b/asg/tests/pass/integers/u16/div.leo new file mode 100644 index 0000000000..f1dd3fa463 --- /dev/null +++ b/asg/tests/pass/integers/u16/div.leo @@ -0,0 +1,3 @@ +function main(a: u16, b: u16, c: u16) { + console.assert(a / b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u16/eq.leo b/asg/tests/pass/integers/u16/eq.leo new file mode 100644 index 0000000000..a4b4e78b49 --- /dev/null +++ b/asg/tests/pass/integers/u16/eq.leo @@ -0,0 +1,3 @@ +function main(a: u16, b: u16, c: bool) { + console.assert(a == b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u16/ge.leo b/asg/tests/pass/integers/u16/ge.leo new file mode 100644 index 0000000000..4b1da1b27b --- /dev/null +++ b/asg/tests/pass/integers/u16/ge.leo @@ -0,0 +1,3 @@ +function main(a: u16, b: u16, c: bool) { + console.assert(a >= b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u16/gt.leo b/asg/tests/pass/integers/u16/gt.leo new file mode 100644 index 0000000000..2c5ffbe8eb --- /dev/null +++ b/asg/tests/pass/integers/u16/gt.leo @@ -0,0 +1,3 @@ +function main(a: u16, b: u16, c: bool) { + console.assert(a > b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u16/input.leo b/asg/tests/pass/integers/u16/input.leo new file mode 100644 index 0000000000..761f0639d0 --- /dev/null +++ b/asg/tests/pass/integers/u16/input.leo @@ -0,0 +1,3 @@ +function main(a: u16, b: u16) { + console.assert(a == b); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u16/le.leo b/asg/tests/pass/integers/u16/le.leo new file mode 100644 index 0000000000..49713482d0 --- /dev/null +++ b/asg/tests/pass/integers/u16/le.leo @@ -0,0 +1,3 @@ +function main(a: u16, b: u16, c: bool) { + console.assert(a <= b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u16/lt.leo b/asg/tests/pass/integers/u16/lt.leo new file mode 100644 index 0000000000..dae1951231 --- /dev/null +++ b/asg/tests/pass/integers/u16/lt.leo @@ -0,0 +1,3 @@ +function main(a: u16, b: u16, c: bool) { + console.assert(a < b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u16/max.leo b/asg/tests/pass/integers/u16/max.leo new file mode 100644 index 0000000000..a707df9af8 --- /dev/null +++ b/asg/tests/pass/integers/u16/max.leo @@ -0,0 +1,3 @@ +function main() { + let a: u16 = 65535; +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u16/min.leo b/asg/tests/pass/integers/u16/min.leo new file mode 100644 index 0000000000..ab1bd7db48 --- /dev/null +++ b/asg/tests/pass/integers/u16/min.leo @@ -0,0 +1,3 @@ +function main() { + let a: u16 = 0; +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u16/mod.rs b/asg/tests/pass/integers/u16/mod.rs new file mode 100644 index 0000000000..da4af3c797 --- /dev/null +++ b/asg/tests/pass/integers/u16/mod.rs @@ -0,0 +1,110 @@ +// 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 . + +// 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 . + +use super::IntegerTester; + +test_uint!(TestU16); + +#[test] +fn test_u16_min() { + TestU16::test_min(); +} + +#[test] +fn test_u16_max() { + TestU16::test_max(); +} + +#[test] +fn test_u16_add() { + TestU16::test_add(); +} + +#[test] +fn test_u16_sub() { + TestU16::test_sub(); +} + +#[test] +fn test_u16_mul() { + TestU16::test_mul(); +} + +#[test] +fn test_u16_div() { + TestU16::test_div(); +} + +#[test] +fn test_u16_pow() { + TestU16::test_pow(); +} + +#[test] +fn test_u16_eq() { + TestU16::test_eq(); +} + +#[test] +fn test_u16_ne() { + TestU16::test_ne(); +} + +#[test] +fn test_u16_ge() { + TestU16::test_ge(); +} + +#[test] +fn test_u16_gt() { + TestU16::test_gt(); +} + +#[test] +fn test_u16_le() { + TestU16::test_le(); +} + +#[test] +fn test_u16_lt() { + TestU16::test_lt(); +} + +#[test] +fn test_u16_console_assert() { + TestU16::test_console_assert(); +} + +#[test] +fn test_u16_ternary() { + TestU16::test_ternary(); +} diff --git a/asg/tests/pass/integers/u16/mul.leo b/asg/tests/pass/integers/u16/mul.leo new file mode 100644 index 0000000000..f2c6f0aac8 --- /dev/null +++ b/asg/tests/pass/integers/u16/mul.leo @@ -0,0 +1,3 @@ +function main(a: u16, b: u16, c: u16) { + console.assert(a * b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u16/ne.leo b/asg/tests/pass/integers/u16/ne.leo new file mode 100644 index 0000000000..e90a304cfe --- /dev/null +++ b/asg/tests/pass/integers/u16/ne.leo @@ -0,0 +1,3 @@ +function main(a: u16, b: u16, c: bool) { + console.assert(a != b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u16/pow.leo b/asg/tests/pass/integers/u16/pow.leo new file mode 100644 index 0000000000..564c1c51fe --- /dev/null +++ b/asg/tests/pass/integers/u16/pow.leo @@ -0,0 +1,3 @@ +function main(a: u16, b: u16, c: u16) { + console.assert(a ** b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u16/sub.leo b/asg/tests/pass/integers/u16/sub.leo new file mode 100644 index 0000000000..92aae9ac2c --- /dev/null +++ b/asg/tests/pass/integers/u16/sub.leo @@ -0,0 +1,3 @@ +function main(a: u16, b: u16, c: u16) { + console.assert(a - b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u16/ternary.leo b/asg/tests/pass/integers/u16/ternary.leo new file mode 100644 index 0000000000..2e2752a130 --- /dev/null +++ b/asg/tests/pass/integers/u16/ternary.leo @@ -0,0 +1,5 @@ +function main(s: bool, a: u16, b: u16, c: u16) { + let r = if s ? a : b; + + console.assert(r == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u32/add.leo b/asg/tests/pass/integers/u32/add.leo new file mode 100644 index 0000000000..6f6a2454b4 --- /dev/null +++ b/asg/tests/pass/integers/u32/add.leo @@ -0,0 +1,3 @@ +function main(a: u32, b: u32, c: u32) { + console.assert(a + b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u32/console_assert.leo b/asg/tests/pass/integers/u32/console_assert.leo new file mode 100644 index 0000000000..32604eb3b8 --- /dev/null +++ b/asg/tests/pass/integers/u32/console_assert.leo @@ -0,0 +1,3 @@ +function main(a: u32, b: u32) { + console.assert(a == b); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u32/div.leo b/asg/tests/pass/integers/u32/div.leo new file mode 100644 index 0000000000..ed689bd408 --- /dev/null +++ b/asg/tests/pass/integers/u32/div.leo @@ -0,0 +1,3 @@ +function main(a: u32, b: u32, c: u32) { + console.assert(a / b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u32/eq.leo b/asg/tests/pass/integers/u32/eq.leo new file mode 100644 index 0000000000..ca427b3c42 --- /dev/null +++ b/asg/tests/pass/integers/u32/eq.leo @@ -0,0 +1,3 @@ +function main(a: u32, b: u32, c: bool) { + console.assert(a == b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u32/ge.leo b/asg/tests/pass/integers/u32/ge.leo new file mode 100644 index 0000000000..35c1c71829 --- /dev/null +++ b/asg/tests/pass/integers/u32/ge.leo @@ -0,0 +1,3 @@ +function main(a: u32, b: u32, c: bool) { + console.assert(a >= b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u32/gt.leo b/asg/tests/pass/integers/u32/gt.leo new file mode 100644 index 0000000000..f76df415c4 --- /dev/null +++ b/asg/tests/pass/integers/u32/gt.leo @@ -0,0 +1,3 @@ +function main(a: u32, b: u32, c: bool) { + console.assert(a > b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u32/input.leo b/asg/tests/pass/integers/u32/input.leo new file mode 100644 index 0000000000..32604eb3b8 --- /dev/null +++ b/asg/tests/pass/integers/u32/input.leo @@ -0,0 +1,3 @@ +function main(a: u32, b: u32) { + console.assert(a == b); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u32/le.leo b/asg/tests/pass/integers/u32/le.leo new file mode 100644 index 0000000000..9a802f896d --- /dev/null +++ b/asg/tests/pass/integers/u32/le.leo @@ -0,0 +1,3 @@ +function main(a: u32, b: u32, c: bool) { + console.assert(a <= b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u32/lt.leo b/asg/tests/pass/integers/u32/lt.leo new file mode 100644 index 0000000000..73e5654470 --- /dev/null +++ b/asg/tests/pass/integers/u32/lt.leo @@ -0,0 +1,3 @@ +function main(a: u32, b: u32, c: bool) { + console.assert(a < b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u32/max.leo b/asg/tests/pass/integers/u32/max.leo new file mode 100644 index 0000000000..2950164a08 --- /dev/null +++ b/asg/tests/pass/integers/u32/max.leo @@ -0,0 +1,3 @@ +function main() { + let a: u32 = 4294967295; +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u32/min.leo b/asg/tests/pass/integers/u32/min.leo new file mode 100644 index 0000000000..0f1c080938 --- /dev/null +++ b/asg/tests/pass/integers/u32/min.leo @@ -0,0 +1,3 @@ +function main() { + let a: u32 = 0; +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u32/mod.rs b/asg/tests/pass/integers/u32/mod.rs new file mode 100644 index 0000000000..64668acff5 --- /dev/null +++ b/asg/tests/pass/integers/u32/mod.rs @@ -0,0 +1,110 @@ +// 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 . + +// 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 . + +use super::IntegerTester; + +test_uint!(TestU32); + +#[test] +fn test_u32_min() { + TestU32::test_min(); +} + +#[test] +fn test_u32_max() { + TestU32::test_max(); +} + +#[test] +fn test_u32_add() { + TestU32::test_add(); +} + +#[test] +fn test_u32_sub() { + TestU32::test_sub(); +} + +#[test] +fn test_u32_mul() { + TestU32::test_mul(); +} + +#[test] +fn test_u32_div() { + TestU32::test_div(); +} + +#[test] +fn test_u32_pow() { + TestU32::test_pow(); +} + +#[test] +fn test_u32_eq() { + TestU32::test_eq(); +} + +#[test] +fn test_u32_ne() { + TestU32::test_ne(); +} + +#[test] +fn test_u32_ge() { + TestU32::test_ge(); +} + +#[test] +fn test_u32_gt() { + TestU32::test_gt(); +} + +#[test] +fn test_u32_le() { + TestU32::test_le(); +} + +#[test] +fn test_u32_lt() { + TestU32::test_lt(); +} + +#[test] +fn test_u32_console_assert() { + TestU32::test_console_assert(); +} + +#[test] +fn test_u32_ternary() { + TestU32::test_ternary(); +} diff --git a/asg/tests/pass/integers/u32/mul.leo b/asg/tests/pass/integers/u32/mul.leo new file mode 100644 index 0000000000..a77a85477b --- /dev/null +++ b/asg/tests/pass/integers/u32/mul.leo @@ -0,0 +1,3 @@ +function main(a: u32, b: u32, c: u32) { + console.assert(a * b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u32/ne.leo b/asg/tests/pass/integers/u32/ne.leo new file mode 100644 index 0000000000..00ee1a9989 --- /dev/null +++ b/asg/tests/pass/integers/u32/ne.leo @@ -0,0 +1,3 @@ +function main(a: u32, b: u32, c: bool) { + console.assert(a != b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u32/pow.leo b/asg/tests/pass/integers/u32/pow.leo new file mode 100644 index 0000000000..b82496ff77 --- /dev/null +++ b/asg/tests/pass/integers/u32/pow.leo @@ -0,0 +1,3 @@ +function main(a: u32, b: u32, c: u32) { + console.assert(a ** b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u32/sub.leo b/asg/tests/pass/integers/u32/sub.leo new file mode 100644 index 0000000000..54480bd4bc --- /dev/null +++ b/asg/tests/pass/integers/u32/sub.leo @@ -0,0 +1,3 @@ +function main(a: u32, b: u32, c: u32) { + console.assert(a - b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u32/ternary.leo b/asg/tests/pass/integers/u32/ternary.leo new file mode 100644 index 0000000000..fde04ac4b8 --- /dev/null +++ b/asg/tests/pass/integers/u32/ternary.leo @@ -0,0 +1,5 @@ +function main(s: bool, a: u32, b: u32, c: u32) { + let r = if s ? a : b; + + console.assert(r == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u64/add.leo b/asg/tests/pass/integers/u64/add.leo new file mode 100644 index 0000000000..28abe51201 --- /dev/null +++ b/asg/tests/pass/integers/u64/add.leo @@ -0,0 +1,3 @@ +function main(a: u64, b: u64, c: u64) { + console.assert(a + b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u64/console_assert.leo b/asg/tests/pass/integers/u64/console_assert.leo new file mode 100644 index 0000000000..ac1d6d40c3 --- /dev/null +++ b/asg/tests/pass/integers/u64/console_assert.leo @@ -0,0 +1,3 @@ +function main(a: u64, b: u64) { + console.assert(a == b); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u64/div.leo b/asg/tests/pass/integers/u64/div.leo new file mode 100644 index 0000000000..059da236bb --- /dev/null +++ b/asg/tests/pass/integers/u64/div.leo @@ -0,0 +1,3 @@ +function main(a: u64, b: u64, c: u64) { + console.assert(a / b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u64/eq.leo b/asg/tests/pass/integers/u64/eq.leo new file mode 100644 index 0000000000..990b2dad2d --- /dev/null +++ b/asg/tests/pass/integers/u64/eq.leo @@ -0,0 +1,3 @@ +function main(a: u64, b: u64, c: bool) { + console.assert(a == b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u64/ge.leo b/asg/tests/pass/integers/u64/ge.leo new file mode 100644 index 0000000000..46ba36ceff --- /dev/null +++ b/asg/tests/pass/integers/u64/ge.leo @@ -0,0 +1,3 @@ +function main(a: u64, b: u64, c: bool) { + console.assert(a >= b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u64/gt.leo b/asg/tests/pass/integers/u64/gt.leo new file mode 100644 index 0000000000..7d3032c7f5 --- /dev/null +++ b/asg/tests/pass/integers/u64/gt.leo @@ -0,0 +1,3 @@ +function main(a: u64, b: u64, c: bool) { + console.assert(a > b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u64/input.leo b/asg/tests/pass/integers/u64/input.leo new file mode 100644 index 0000000000..ac1d6d40c3 --- /dev/null +++ b/asg/tests/pass/integers/u64/input.leo @@ -0,0 +1,3 @@ +function main(a: u64, b: u64) { + console.assert(a == b); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u64/le.leo b/asg/tests/pass/integers/u64/le.leo new file mode 100644 index 0000000000..625b38d2d9 --- /dev/null +++ b/asg/tests/pass/integers/u64/le.leo @@ -0,0 +1,3 @@ +function main(a: u64, b: u64, c: bool) { + console.assert(a <= b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u64/lt.leo b/asg/tests/pass/integers/u64/lt.leo new file mode 100644 index 0000000000..ed379f7341 --- /dev/null +++ b/asg/tests/pass/integers/u64/lt.leo @@ -0,0 +1,3 @@ +function main(a: u64, b: u64, c: bool) { + console.assert(a < b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u64/max.leo b/asg/tests/pass/integers/u64/max.leo new file mode 100644 index 0000000000..985897c006 --- /dev/null +++ b/asg/tests/pass/integers/u64/max.leo @@ -0,0 +1,3 @@ +function main() { + let a: u64 = 18446744073709551615; +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u64/min.leo b/asg/tests/pass/integers/u64/min.leo new file mode 100644 index 0000000000..aa9b72fc8a --- /dev/null +++ b/asg/tests/pass/integers/u64/min.leo @@ -0,0 +1,3 @@ +function main() { + let a: u64 = 0; +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u64/mod.rs b/asg/tests/pass/integers/u64/mod.rs new file mode 100644 index 0000000000..81ef097ce7 --- /dev/null +++ b/asg/tests/pass/integers/u64/mod.rs @@ -0,0 +1,110 @@ +// 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 . + +// 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 . + +use super::IntegerTester; + +test_uint!(TestU64); + +#[test] +fn test_u64_min() { + TestU64::test_min(); +} + +#[test] +fn test_u64_max() { + TestU64::test_max(); +} + +#[test] +fn test_u64_add() { + TestU64::test_add(); +} + +#[test] +fn test_u64_sub() { + TestU64::test_sub(); +} + +#[test] +fn test_u64_mul() { + TestU64::test_mul(); +} + +#[test] +fn test_u64_div() { + TestU64::test_div(); +} + +#[test] +fn test_u64_pow() { + TestU64::test_pow(); +} + +#[test] +fn test_u64_eq() { + TestU64::test_eq(); +} + +#[test] +fn test_u64_ne() { + TestU64::test_ne(); +} + +#[test] +fn test_u64_ge() { + TestU64::test_ge(); +} + +#[test] +fn test_u64_gt() { + TestU64::test_gt(); +} + +#[test] +fn test_u64_le() { + TestU64::test_le(); +} + +#[test] +fn test_u64_lt() { + TestU64::test_lt(); +} + +#[test] +fn test_u64_console_assert() { + TestU64::test_console_assert(); +} + +#[test] +fn test_u64_ternary() { + TestU64::test_ternary(); +} diff --git a/asg/tests/pass/integers/u64/mul.leo b/asg/tests/pass/integers/u64/mul.leo new file mode 100644 index 0000000000..2633e6780c --- /dev/null +++ b/asg/tests/pass/integers/u64/mul.leo @@ -0,0 +1,3 @@ +function main(a: u64, b: u64, c: u64) { + console.assert(a * b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u64/ne.leo b/asg/tests/pass/integers/u64/ne.leo new file mode 100644 index 0000000000..e47acbb1de --- /dev/null +++ b/asg/tests/pass/integers/u64/ne.leo @@ -0,0 +1,3 @@ +function main(a: u64, b: u64, c: bool) { + console.assert(a != b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u64/pow.leo b/asg/tests/pass/integers/u64/pow.leo new file mode 100644 index 0000000000..64f0694ed1 --- /dev/null +++ b/asg/tests/pass/integers/u64/pow.leo @@ -0,0 +1,3 @@ +function main(a: u64, b: u64, c: u64) { + console.assert(a ** b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u64/sub.leo b/asg/tests/pass/integers/u64/sub.leo new file mode 100644 index 0000000000..9961f0f7b7 --- /dev/null +++ b/asg/tests/pass/integers/u64/sub.leo @@ -0,0 +1,3 @@ +function main(a: u64, b: u64, c: u64) { + console.assert(a - b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u64/ternary.leo b/asg/tests/pass/integers/u64/ternary.leo new file mode 100644 index 0000000000..315fd7400b --- /dev/null +++ b/asg/tests/pass/integers/u64/ternary.leo @@ -0,0 +1,5 @@ +function main(s: bool, a: u64, b: u64, c: u64) { + let r = if s ? a : b; + + console.assert(r == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u8/add.leo b/asg/tests/pass/integers/u8/add.leo new file mode 100644 index 0000000000..1b40e304d2 --- /dev/null +++ b/asg/tests/pass/integers/u8/add.leo @@ -0,0 +1,3 @@ +function main(a: u8, b: u8, c: u8) { + console.assert(a + b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u8/console_assert.leo b/asg/tests/pass/integers/u8/console_assert.leo new file mode 100644 index 0000000000..4d99dc106c --- /dev/null +++ b/asg/tests/pass/integers/u8/console_assert.leo @@ -0,0 +1,3 @@ +function main(a: u8, b: u8) { + console.assert(a == b); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u8/div.leo b/asg/tests/pass/integers/u8/div.leo new file mode 100644 index 0000000000..945aa94c30 --- /dev/null +++ b/asg/tests/pass/integers/u8/div.leo @@ -0,0 +1,3 @@ +function main(a: u8, b: u8, c: u8) { + console.assert(a / b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u8/eq.leo b/asg/tests/pass/integers/u8/eq.leo new file mode 100644 index 0000000000..c2a487b0e7 --- /dev/null +++ b/asg/tests/pass/integers/u8/eq.leo @@ -0,0 +1,3 @@ +function main(a: u8, b: u8, c: bool) { + console.assert(a == b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u8/ge.leo b/asg/tests/pass/integers/u8/ge.leo new file mode 100644 index 0000000000..d819422276 --- /dev/null +++ b/asg/tests/pass/integers/u8/ge.leo @@ -0,0 +1,3 @@ +function main(a: u8, b: u8, c: bool) { + console.assert(a >= b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u8/gt.leo b/asg/tests/pass/integers/u8/gt.leo new file mode 100644 index 0000000000..87843f575f --- /dev/null +++ b/asg/tests/pass/integers/u8/gt.leo @@ -0,0 +1,3 @@ +function main(a: u8, b: u8, c: bool) { + console.assert(a > b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u8/input.leo b/asg/tests/pass/integers/u8/input.leo new file mode 100644 index 0000000000..4d99dc106c --- /dev/null +++ b/asg/tests/pass/integers/u8/input.leo @@ -0,0 +1,3 @@ +function main(a: u8, b: u8) { + console.assert(a == b); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u8/le.leo b/asg/tests/pass/integers/u8/le.leo new file mode 100644 index 0000000000..2607b7f3d1 --- /dev/null +++ b/asg/tests/pass/integers/u8/le.leo @@ -0,0 +1,3 @@ +function main(a: u8, b: u8, c: bool) { + console.assert(a <= b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u8/lt.leo b/asg/tests/pass/integers/u8/lt.leo new file mode 100644 index 0000000000..7495d0fe37 --- /dev/null +++ b/asg/tests/pass/integers/u8/lt.leo @@ -0,0 +1,3 @@ +function main(a: u8, b: u8, c: bool) { + console.assert(a < b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u8/max.leo b/asg/tests/pass/integers/u8/max.leo new file mode 100644 index 0000000000..684bdfba10 --- /dev/null +++ b/asg/tests/pass/integers/u8/max.leo @@ -0,0 +1,3 @@ +function main() { + let a: u8 = 255; +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u8/min.leo b/asg/tests/pass/integers/u8/min.leo new file mode 100644 index 0000000000..a88e33c5a6 --- /dev/null +++ b/asg/tests/pass/integers/u8/min.leo @@ -0,0 +1,3 @@ +function main() { + let a: u8 = 0; +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u8/mod.rs b/asg/tests/pass/integers/u8/mod.rs new file mode 100644 index 0000000000..ee298c8f42 --- /dev/null +++ b/asg/tests/pass/integers/u8/mod.rs @@ -0,0 +1,110 @@ +// 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 . + +// 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 . + +use super::IntegerTester; + +test_uint!(TestU8); + +#[test] +fn test_u8_min() { + TestU8::test_min(); +} + +#[test] +fn test_u8_max() { + TestU8::test_max(); +} + +#[test] +fn test_u8_add() { + TestU8::test_add(); +} + +#[test] +fn test_u8_sub() { + TestU8::test_sub(); +} + +#[test] +fn test_u8_mul() { + TestU8::test_mul(); +} + +#[test] +fn test_u8_div() { + TestU8::test_div(); +} + +#[test] +fn test_u8_pow() { + TestU8::test_pow(); +} + +#[test] +fn test_u8_eq() { + TestU8::test_eq(); +} + +#[test] +fn test_u8_ne() { + TestU8::test_ne(); +} + +#[test] +fn test_u8_ge() { + TestU8::test_ge(); +} + +#[test] +fn test_u8_gt() { + TestU8::test_gt(); +} + +#[test] +fn test_u8_le() { + TestU8::test_le(); +} + +#[test] +fn test_u8_lt() { + TestU8::test_lt(); +} + +#[test] +fn test_u8_console_assert() { + TestU8::test_console_assert(); +} + +#[test] +fn test_u8_ternary() { + TestU8::test_ternary(); +} diff --git a/asg/tests/pass/integers/u8/mul.leo b/asg/tests/pass/integers/u8/mul.leo new file mode 100644 index 0000000000..11acf4688b --- /dev/null +++ b/asg/tests/pass/integers/u8/mul.leo @@ -0,0 +1,3 @@ +function main(a: u8, b: u8, c: u8) { + console.assert(a * b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u8/ne.leo b/asg/tests/pass/integers/u8/ne.leo new file mode 100644 index 0000000000..e75194a2f2 --- /dev/null +++ b/asg/tests/pass/integers/u8/ne.leo @@ -0,0 +1,3 @@ +function main(a: u8, b: u8, c: bool) { + console.assert(a != b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u8/pow.leo b/asg/tests/pass/integers/u8/pow.leo new file mode 100644 index 0000000000..928ab73b0d --- /dev/null +++ b/asg/tests/pass/integers/u8/pow.leo @@ -0,0 +1,3 @@ +function main(a: u8, b: u8, c: u8) { + console.assert(a ** b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u8/sub.leo b/asg/tests/pass/integers/u8/sub.leo new file mode 100644 index 0000000000..1335409c29 --- /dev/null +++ b/asg/tests/pass/integers/u8/sub.leo @@ -0,0 +1,3 @@ +function main(a: u8, b: u8, c: u8) { + console.assert(a - b == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/u8/ternary.leo b/asg/tests/pass/integers/u8/ternary.leo new file mode 100644 index 0000000000..ce868a5ec9 --- /dev/null +++ b/asg/tests/pass/integers/u8/ternary.leo @@ -0,0 +1,5 @@ +function main(s: bool, a: u8, b: u8, c: u8) { + let r = if s ? a : b; + + console.assert(r == c); +} \ No newline at end of file diff --git a/asg/tests/pass/integers/uint_macro.rs b/asg/tests/pass/integers/uint_macro.rs new file mode 100644 index 0000000000..7ca8ba3325 --- /dev/null +++ b/asg/tests/pass/integers/uint_macro.rs @@ -0,0 +1,114 @@ +// 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 . + +// 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 . + +macro_rules! test_uint { + ($name: ident) => { + pub struct $name {} + + impl super::IntegerTester for $name { + fn test_min() { + let program_string = include_str!("min.leo"); + crate::load_asg(program_string).unwrap(); + } + + fn test_max() { + let program_string = include_str!("max.leo"); + crate::load_asg(program_string).unwrap(); + } + + fn test_add() { + let program_string = include_str!("add.leo"); + crate::load_asg(program_string).unwrap(); + } + + fn test_sub() { + let program_string = include_str!("sub.leo"); + crate::load_asg(program_string).unwrap(); + } + + fn test_mul() { + let program_string = include_str!("mul.leo"); + crate::load_asg(program_string).unwrap(); + } + + fn test_div() { + let program_string = include_str!("div.leo"); + crate::load_asg(program_string).unwrap(); + } + + fn test_pow() { + let program_string = include_str!("pow.leo"); + crate::load_asg(program_string).unwrap(); + } + + fn test_eq() { + let program_string = include_str!("eq.leo"); + crate::load_asg(program_string).unwrap(); + } + + fn test_ne() { + let program_string = include_str!("ne.leo"); + crate::load_asg(program_string).unwrap(); + } + + fn test_ge() { + let program_string = include_str!("ge.leo"); + crate::load_asg(program_string).unwrap(); + } + + fn test_gt() { + let program_string = include_str!("gt.leo"); + crate::load_asg(program_string).unwrap(); + } + + fn test_le() { + let program_string = include_str!("le.leo"); + crate::load_asg(program_string).unwrap(); + } + + fn test_lt() { + let program_string = include_str!("lt.leo"); + crate::load_asg(program_string).unwrap(); + } + + fn test_console_assert() { + let program_string = include_str!("console_assert.leo"); + crate::load_asg(program_string).unwrap(); + } + + fn test_ternary() { + let program_string = include_str!("ternary.leo"); + crate::load_asg(program_string).unwrap(); + } + } + }; +} diff --git a/asg/tests/pass/mod.rs b/asg/tests/pass/mod.rs new file mode 100644 index 0000000000..fa986b91c0 --- /dev/null +++ b/asg/tests/pass/mod.rs @@ -0,0 +1,49 @@ +// 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 . + +// 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 . + +pub mod address; +pub mod array; +pub mod boolean; +pub mod circuits; +pub mod console; +pub mod core; +pub mod definition; +pub mod field; +pub mod form_ast; +pub mod function; +pub mod group; +pub mod import; +pub mod input_files; +pub mod integers; +pub mod mutability; +pub mod statements; +pub mod tuples; diff --git a/asg/tests/pass/mutability/array_mut.leo b/asg/tests/pass/mutability/array_mut.leo new file mode 100644 index 0000000000..1b86bac80f --- /dev/null +++ b/asg/tests/pass/mutability/array_mut.leo @@ -0,0 +1,7 @@ +// Adding the `mut` keyword makes an array variable mutable. +function main() { + let mut a = [1u32]; + a[0] = 0; + + console.assert(a[0] == 0u32); +} \ No newline at end of file diff --git a/asg/tests/pass/mutability/array_splice_mut.leo b/asg/tests/pass/mutability/array_splice_mut.leo new file mode 100644 index 0000000000..57cc67e872 --- /dev/null +++ b/asg/tests/pass/mutability/array_splice_mut.leo @@ -0,0 +1,9 @@ +// Adding the `mut` keyword makes an array variable mutable. +function main() { + let mut a = [1u32, 2u32, 3u32]; + a[0u32..2u32] = [4u32, 5u32]; + + console.assert(a[0] == 4u32); + console.assert(a[1] == 5u32); + console.assert(a[2] == 3u32); +} \ No newline at end of file diff --git a/asg/tests/pass/mutability/array_tuple_mut.leo b/asg/tests/pass/mutability/array_tuple_mut.leo new file mode 100644 index 0000000000..e0096bd7ac --- /dev/null +++ b/asg/tests/pass/mutability/array_tuple_mut.leo @@ -0,0 +1,8 @@ +// Adding the `mut` keyword makes an array variable mutable. +function main() { + let mut a = [(1u32, 2u32)]; + a[0u32].1 = 3u32; + + console.assert(a[0u32].0 == 1u32); + console.assert(a[0u32].1 == 3u32); +} \ No newline at end of file diff --git a/asg/tests/pass/mutability/circuit_mut.leo b/asg/tests/pass/mutability/circuit_mut.leo new file mode 100644 index 0000000000..27bd6109b2 --- /dev/null +++ b/asg/tests/pass/mutability/circuit_mut.leo @@ -0,0 +1,11 @@ +// Adding the `mut` keyword makes a circuit variable mutable. +circuit Foo { + x: u32 +} + +function main() { + let mut a = Foo { x: 1 }; + a.x = 0; + + console.assert(a.x == 0u32); +} \ No newline at end of file diff --git a/asg/tests/pass/mutability/circuit_variable_mut.leo b/asg/tests/pass/mutability/circuit_variable_mut.leo new file mode 100644 index 0000000000..27bd6109b2 --- /dev/null +++ b/asg/tests/pass/mutability/circuit_variable_mut.leo @@ -0,0 +1,11 @@ +// Adding the `mut` keyword makes a circuit variable mutable. +circuit Foo { + x: u32 +} + +function main() { + let mut a = Foo { x: 1 }; + a.x = 0; + + console.assert(a.x == 0u32); +} \ No newline at end of file diff --git a/asg/tests/pass/mutability/function_input_mut.leo b/asg/tests/pass/mutability/function_input_mut.leo new file mode 100644 index 0000000000..2df24b227c --- /dev/null +++ b/asg/tests/pass/mutability/function_input_mut.leo @@ -0,0 +1,6 @@ +// Adding the `mut` keyword makes a function variable mutable. +function main(mut a: bool) { + a = true; + + console.assert(a == true); +} \ No newline at end of file diff --git a/asg/tests/pass/mutability/let_mut.leo b/asg/tests/pass/mutability/let_mut.leo new file mode 100644 index 0000000000..5766d144d3 --- /dev/null +++ b/asg/tests/pass/mutability/let_mut.leo @@ -0,0 +1,7 @@ +// Adding the `mut` keyword makes a variable mutable. +function main() { + let mut a = 1u32; + a = 0; + + console.assert(a == 0u32); +} \ No newline at end of file diff --git a/asg/tests/pass/mutability/let_mut_nested.leo b/asg/tests/pass/mutability/let_mut_nested.leo new file mode 100644 index 0000000000..27121f6e48 --- /dev/null +++ b/asg/tests/pass/mutability/let_mut_nested.leo @@ -0,0 +1,5 @@ +function main () { + let mut x = 2u8; + let mut y = x; + let z = y / 2u8; +} \ No newline at end of file diff --git a/asg/tests/pass/mutability/mod.rs b/asg/tests/pass/mutability/mod.rs new file mode 100644 index 0000000000..12dd50b9bb --- /dev/null +++ b/asg/tests/pass/mutability/mod.rs @@ -0,0 +1,88 @@ +// 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 . + +// 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 . + +use crate::load_asg; + +#[test] +fn test_let_mut() { + let program_string = include_str!("let_mut.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_let_mut_nested() { + let program_string = include_str!("let_mut_nested.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_array_mut() { + let program_string = include_str!("array_mut.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_array_tuple_mut() { + let program_string = include_str!("array_tuple_mut.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_array_splice_mut() { + let program_string = include_str!("array_splice_mut.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_circuit_mut() { + let program_string = include_str!("circuit_mut.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_circuit_variable_mut() { + let program_string = include_str!("circuit_variable_mut.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_function_input_mut() { + let program_string = include_str!("function_input_mut.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +#[ignore] +fn test_swap() { + let program_string = include_str!("swap.leo"); + load_asg(program_string).unwrap(); +} diff --git a/asg/tests/pass/mutability/swap.leo b/asg/tests/pass/mutability/swap.leo new file mode 100644 index 0000000000..8234a3cfb7 --- /dev/null +++ b/asg/tests/pass/mutability/swap.leo @@ -0,0 +1,20 @@ +// Swap two elements of an array. +function swap(mut a: [u32; 2], i: u32, j: u32) -> [u32; 2] { + let t = a[i]; + a[i] = a[j]; + a[j] = t; + return a +} + +function main() { + let mut arr: [u32; 2] = [0, 1]; + let expected: [u32; 2] = [1, 0]; + + // Do swap. + let actual = swap(arr, 0, 1); + + // Check result. + for i in 0..2 { + console.assert(expected[i] == actual[i]); + } +} \ No newline at end of file diff --git a/asg/tests/pass/statements/block.leo b/asg/tests/pass/statements/block.leo new file mode 100644 index 0000000000..8650808041 --- /dev/null +++ b/asg/tests/pass/statements/block.leo @@ -0,0 +1,9 @@ +function main() { + let mut x = 4u32; + + { + x = 5u32; + } + + console.assert(x == 5u32); +} \ No newline at end of file diff --git a/asg/tests/pass/statements/conditional/assert.leo b/asg/tests/pass/statements/conditional/assert.leo new file mode 100644 index 0000000000..f3d20b461d --- /dev/null +++ b/asg/tests/pass/statements/conditional/assert.leo @@ -0,0 +1,7 @@ +function main(a: u32) { + if a == 1 { + console.assert(a == 1); + } else { + console.assert(a == 0); + } +} diff --git a/asg/tests/pass/statements/conditional/chain.leo b/asg/tests/pass/statements/conditional/chain.leo new file mode 100644 index 0000000000..dbc0e1f38c --- /dev/null +++ b/asg/tests/pass/statements/conditional/chain.leo @@ -0,0 +1,13 @@ +function main(a: u32, b: u32) { + let mut c = 0u32; + + if a == 1 { + c = 1; + } else if a == 2 { + c = 2; + } else { + c = 3; + } + + console.assert(c == b); +} \ No newline at end of file diff --git a/asg/tests/pass/statements/conditional/for_loop.leo b/asg/tests/pass/statements/conditional/for_loop.leo new file mode 100644 index 0000000000..060d27d965 --- /dev/null +++ b/asg/tests/pass/statements/conditional/for_loop.leo @@ -0,0 +1,13 @@ +function main(a: bool) { + let mut b = 0u32; + + if a { + for i in 0..4 { + b += i; + } + } + + let r: u32 = if a ? 6 : 0; + + console.assert(r == b); +} diff --git a/asg/tests/pass/statements/conditional/mod.rs b/asg/tests/pass/statements/conditional/mod.rs new file mode 100644 index 0000000000..2d43bda21a --- /dev/null +++ b/asg/tests/pass/statements/conditional/mod.rs @@ -0,0 +1,69 @@ +// 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 . + +// 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 . + +use crate::load_asg; + +#[test] +fn test_assert() { + let program_string = include_str!("assert.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_mutate() { + let program_string = include_str!("mutate.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_for_loop() { + let program_string = include_str!("for_loop.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_chain() { + let program_string = include_str!("chain.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_nested() { + let program_string = include_str!("nested.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_multiple_returns() { + let program_string = include_str!("multiple_returns.leo"); + load_asg(program_string).unwrap(); +} diff --git a/asg/tests/pass/statements/conditional/multiple_returns.leo b/asg/tests/pass/statements/conditional/multiple_returns.leo new file mode 100644 index 0000000000..b8dd869b47 --- /dev/null +++ b/asg/tests/pass/statements/conditional/multiple_returns.leo @@ -0,0 +1,7 @@ +function main(input) -> u32 { + if input.registers.a == 0u32 { + return 0u32 + } else { + return 1u32 + } +} \ No newline at end of file diff --git a/asg/tests/pass/statements/conditional/mutate.leo b/asg/tests/pass/statements/conditional/mutate.leo new file mode 100644 index 0000000000..458d3d0d60 --- /dev/null +++ b/asg/tests/pass/statements/conditional/mutate.leo @@ -0,0 +1,15 @@ +function main(a: u32) { + let mut b = 5u32; + + if a == 1 { + b = 1; + } else { + b = 0; + } + + if a == 1 { + console.assert(b == 1); + } else { + console.assert(b == 0); + } +} diff --git a/asg/tests/pass/statements/conditional/nested.leo b/asg/tests/pass/statements/conditional/nested.leo new file mode 100644 index 0000000000..3596f889d1 --- /dev/null +++ b/asg/tests/pass/statements/conditional/nested.leo @@ -0,0 +1,12 @@ +function main(a: bool, b: bool, c: u32) { + let mut d = 0u32; + + if a { + d += 1; + if b { + d += 2; + } + } + + console.assert(d == c); +} \ No newline at end of file diff --git a/asg/tests/pass/statements/iteration_basic.leo b/asg/tests/pass/statements/iteration_basic.leo new file mode 100644 index 0000000000..103c9abb9e --- /dev/null +++ b/asg/tests/pass/statements/iteration_basic.leo @@ -0,0 +1,8 @@ +function main() { + let mut x = 4u32; + for i in 0..3 { + x -= 1; + } + + console.assert(x == 1u32); +} \ No newline at end of file diff --git a/asg/tests/pass/statements/mod.rs b/asg/tests/pass/statements/mod.rs new file mode 100644 index 0000000000..bd6ed29563 --- /dev/null +++ b/asg/tests/pass/statements/mod.rs @@ -0,0 +1,57 @@ +// 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 . + +// 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 . + +use crate::load_asg; + +pub mod conditional; + +// Ternary if {bool}? {expression} : {expression}; + +#[test] +fn test_ternary_basic() { + let program_string = include_str!("ternary_basic.leo"); + load_asg(program_string).unwrap(); +} + +// Iteration for i {start}..{stop} { statements } + +#[test] +fn test_iteration_basic() { + let program_string = include_str!("iteration_basic.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_block() { + let program_string = include_str!("block.leo"); + load_asg(program_string).unwrap(); +} diff --git a/asg/tests/pass/statements/ternary_basic.leo b/asg/tests/pass/statements/ternary_basic.leo new file mode 100644 index 0000000000..5106363ce2 --- /dev/null +++ b/asg/tests/pass/statements/ternary_basic.leo @@ -0,0 +1,5 @@ +function main(a: bool, b: bool) { + let c = if a ? true : false; + + const d = c == b; +} \ No newline at end of file diff --git a/asg/tests/pass/tuples/access.leo b/asg/tests/pass/tuples/access.leo new file mode 100644 index 0000000000..196e9d058c --- /dev/null +++ b/asg/tests/pass/tuples/access.leo @@ -0,0 +1,6 @@ +function main() { + let a = (true, false); + + console.assert(a.0 == true); + console.assert(a.1 == false); +} \ No newline at end of file diff --git a/asg/tests/pass/tuples/basic.leo b/asg/tests/pass/tuples/basic.leo new file mode 100644 index 0000000000..37c728611c --- /dev/null +++ b/asg/tests/pass/tuples/basic.leo @@ -0,0 +1,3 @@ +function main() { + let a = (true, false); +} \ No newline at end of file diff --git a/asg/tests/pass/tuples/function.leo b/asg/tests/pass/tuples/function.leo new file mode 100644 index 0000000000..b318348813 --- /dev/null +++ b/asg/tests/pass/tuples/function.leo @@ -0,0 +1,10 @@ +function foo() -> (bool, bool) { + return (true, false) +} + +function main() { + let a = foo(); + + console.assert(a.0 == true); + console.assert(a.1 == false); +} \ No newline at end of file diff --git a/asg/tests/pass/tuples/function_multiple.leo b/asg/tests/pass/tuples/function_multiple.leo new file mode 100644 index 0000000000..39848377c6 --- /dev/null +++ b/asg/tests/pass/tuples/function_multiple.leo @@ -0,0 +1,10 @@ +function foo() -> (bool, bool) { + return (true, false) +} + +function main() { + let (a, b) = foo(); + + console.assert(a == true); + console.assert(b == false); +} \ No newline at end of file diff --git a/asg/tests/pass/tuples/function_typed.leo b/asg/tests/pass/tuples/function_typed.leo new file mode 100644 index 0000000000..8af2c907ca --- /dev/null +++ b/asg/tests/pass/tuples/function_typed.leo @@ -0,0 +1,10 @@ +function foo() -> (bool, bool) { + return (true, false) +} + +function main() { + let a: (bool, bool) = foo(); + + console.assert(a.0 == true); + console.assert(a.1 == false); +} \ No newline at end of file diff --git a/asg/tests/pass/tuples/input.leo b/asg/tests/pass/tuples/input.leo new file mode 100644 index 0000000000..f7672a3b03 --- /dev/null +++ b/asg/tests/pass/tuples/input.leo @@ -0,0 +1,3 @@ +function main(a: (bool, bool)) { + +} \ No newline at end of file diff --git a/asg/tests/pass/tuples/mod.rs b/asg/tests/pass/tuples/mod.rs new file mode 100644 index 0000000000..00fad01a43 --- /dev/null +++ b/asg/tests/pass/tuples/mod.rs @@ -0,0 +1,99 @@ +// 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 . + +// 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 . + +use crate::load_asg; + +#[test] +fn test_tuple_basic() { + let program_string = include_str!("basic.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_tuple_access() { + let program_string = include_str!("access.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_tuple_typed() { + let program_string = include_str!("typed.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_multiple() { + let program_string = include_str!("multiple.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_multiple_typed() { + let program_string = include_str!("multiple_typed.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_function() { + let program_string = include_str!("function.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_function_typed() { + let program_string = include_str!("function_typed.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_function_multiple() { + let program_string = include_str!("function_multiple.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_nested() { + let program_string = include_str!("nested.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_nested_access() { + let program_string = include_str!("nested_access.leo"); + load_asg(program_string).unwrap(); +} + +#[test] +fn test_nested_typed() { + let program_string = include_str!("nested_typed.leo"); + load_asg(program_string).unwrap(); +} diff --git a/asg/tests/pass/tuples/multiple.leo b/asg/tests/pass/tuples/multiple.leo new file mode 100644 index 0000000000..b7627dad2a --- /dev/null +++ b/asg/tests/pass/tuples/multiple.leo @@ -0,0 +1,6 @@ +function main() { + let (a, b) = (true, false); + + console.assert(a == true); + console.assert(b == false); +} \ No newline at end of file diff --git a/asg/tests/pass/tuples/multiple_typed.leo b/asg/tests/pass/tuples/multiple_typed.leo new file mode 100644 index 0000000000..29fc7ef877 --- /dev/null +++ b/asg/tests/pass/tuples/multiple_typed.leo @@ -0,0 +1,6 @@ +function main() { + let (a, b): (bool, bool) = (true, false); + + console.assert(a == true); + console.assert(b == false); +} \ No newline at end of file diff --git a/asg/tests/pass/tuples/nested.leo b/asg/tests/pass/tuples/nested.leo new file mode 100644 index 0000000000..a9599b360c --- /dev/null +++ b/asg/tests/pass/tuples/nested.leo @@ -0,0 +1,4 @@ +function main() { + let a = (true, false); + let b = (true, a); +} \ No newline at end of file diff --git a/asg/tests/pass/tuples/nested_access.leo b/asg/tests/pass/tuples/nested_access.leo new file mode 100644 index 0000000000..5edba64e24 --- /dev/null +++ b/asg/tests/pass/tuples/nested_access.leo @@ -0,0 +1,8 @@ +function main() { + let a = (true, false); + let b = (true, a); + + console.assert(b.0 == true); + console.assert(b.1.0 == true); + console.assert(b.1.1 == false); +} \ No newline at end of file diff --git a/asg/tests/pass/tuples/nested_typed.leo b/asg/tests/pass/tuples/nested_typed.leo new file mode 100644 index 0000000000..2e68117a2b --- /dev/null +++ b/asg/tests/pass/tuples/nested_typed.leo @@ -0,0 +1,4 @@ +function main() { + let a = (true, false); + let b: (bool, (bool, bool)) = (true, a); +} \ No newline at end of file diff --git a/asg/tests/pass/tuples/typed.leo b/asg/tests/pass/tuples/typed.leo new file mode 100644 index 0000000000..8cd2ed79db --- /dev/null +++ b/asg/tests/pass/tuples/typed.leo @@ -0,0 +1,3 @@ +function main() { + let a: (bool, bool) = (true, false); +} \ No newline at end of file diff --git a/ast/src/circuits/circuit.rs b/ast/src/circuits/circuit.rs index 010f408c78..25ead98a00 100644 --- a/ast/src/circuits/circuit.rs +++ b/ast/src/circuits/circuit.rs @@ -50,3 +50,9 @@ impl fmt::Debug for Circuit { self.format(f) } } + +impl fmt::Display for Circuit { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.format(f) + } +} diff --git a/ast/src/program.rs b/ast/src/program.rs index 2078682e33..f5edd59336 100644 --- a/ast/src/program.rs +++ b/ast/src/program.rs @@ -31,6 +31,8 @@ use leo_grammar::{definitions::Definition, files::File}; use indexmap::IndexMap; use serde::{Deserialize, Serialize}; +use std::fmt; + /// Stores the Leo program abstract syntax tree. #[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)] pub struct Program { @@ -42,6 +44,31 @@ pub struct Program { pub tests: IndexMap, } +impl fmt::Display for Program { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + for import in self.imports.iter() { + import.fmt(f)?; + writeln!(f,)?; + } + writeln!(f,)?; + for (_, circuit) in self.circuits.iter() { + circuit.fmt(f)?; + writeln!(f,)?; + } + writeln!(f,)?; + for (_, function) in self.functions.iter() { + function.fmt(f)?; + writeln!(f,)?; + } + for (_, test) in self.tests.iter() { + write!(f, "test ")?; + test.function.fmt(f)?; + writeln!(f,)?; + } + write!(f, "") + } +} + const MAIN_FUNCTION_NAME: &str = "main"; impl<'ast> Program { diff --git a/grammar/src/lib.rs b/grammar/src/lib.rs index a9645e6e2f..15d26b9605 100644 --- a/grammar/src/lib.rs +++ b/grammar/src/lib.rs @@ -20,7 +20,6 @@ //! The [`Grammar`] type is the datatype generated by the pest parser using grammar from `leo.pest`. //! The [`Grammar`] type is intended to be parsed into a [`Ast`]. It should not be parsed by //! any other pass of the compiler. - #[macro_use] extern crate lazy_static; #[macro_use]