mirror of
https://github.com/AleoHQ/leo.git
synced 2024-11-28 11:16:49 +03:00
Merge branch 'console-assert-error' of https://github.com/AleoHQ/leo into console-assert-error
This commit is contained in:
commit
c8d1125ad9
@ -1,5 +1,2 @@
|
||||
[build]
|
||||
[target.'cfg(not(target_arch = "wasm32"))']
|
||||
rustflags = ["-C", "target-cpu=native"]
|
||||
|
||||
[net]
|
||||
git-fetch-with-cli = true
|
||||
|
@ -138,6 +138,32 @@ jobs:
|
||||
export LEO=/home/circleci/project/project/bin/leo
|
||||
./project/.circleci/leo-login-logout.sh
|
||||
|
||||
leo-clone:
|
||||
docker:
|
||||
- image: cimg/rust:1.50.0
|
||||
resource_class: xlarge
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: /home/circleci/project/
|
||||
- run:
|
||||
name: leo clone
|
||||
command: |
|
||||
export LEO=/home/circleci/project/project/bin/leo
|
||||
./project/.circleci/leo-clone.sh
|
||||
|
||||
leo-publish:
|
||||
docker:
|
||||
- image: cimg/rust:1.50.0
|
||||
resource_class: xlarge
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: /home/circleci/project/
|
||||
- run:
|
||||
name: leo publish
|
||||
command: |
|
||||
export LEO=/home/circleci/project/project/bin/leo
|
||||
./project/.circleci/leo-publish.sh
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
main-workflow:
|
||||
@ -160,4 +186,10 @@ workflows:
|
||||
- rust-stable
|
||||
- leo-login-logout:
|
||||
requires:
|
||||
- rust-stable
|
||||
- rust-stable
|
||||
- leo-clone:
|
||||
requires:
|
||||
- rust-stable
|
||||
- leo-publish:
|
||||
requires:
|
||||
- rust-stable
|
||||
|
18
.circleci/leo-clone.sh
Executable file
18
.circleci/leo-clone.sh
Executable file
@ -0,0 +1,18 @@
|
||||
# leo clone
|
||||
|
||||
# Clone the test-app package.
|
||||
export PACKAGE="$ALEO_PM_USERNAME/test-app"
|
||||
$LEO clone $PACKAGE
|
||||
|
||||
# Assert that the 'test-app' folder is not empty
|
||||
|
||||
cd test-app || exit 1
|
||||
if [ "$(ls -A $DIR)" ]; then
|
||||
echo "$DIR is not empty"
|
||||
else
|
||||
echo "$DIR is empty"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ls -la
|
||||
$LEO run
|
56
.circleci/leo-publish.sh
Executable file
56
.circleci/leo-publish.sh
Executable file
@ -0,0 +1,56 @@
|
||||
# leo login, publish and logout
|
||||
|
||||
# Login
|
||||
$LEO login -u "$ALEO_PM_USERNAME" -p "$ALEO_PM_PASSWORD"
|
||||
|
||||
# Clone the test-app package.
|
||||
export PACKAGE="$ALEO_PM_USERNAME/test-app"
|
||||
$LEO clone $PACKAGE
|
||||
cd test-app || exit 1
|
||||
|
||||
# Fetch the current Leo package version number.
|
||||
#
|
||||
# 1. Print out the Leo.toml file.
|
||||
# 2. Search for a line with the word "version".
|
||||
# 3. Isolate that into a single line.
|
||||
# 4. Split the line from the '=' sign and keep the right-hand side.
|
||||
# 5. Remove the quotes around the version number.
|
||||
# 6. Trim any excess whitespace.
|
||||
export CURRENT=$(cat Leo.toml \
|
||||
| grep version \
|
||||
| head -1 \
|
||||
| awk -F= '{ print $2 }' \
|
||||
| sed 's/[",]//g' \
|
||||
| xargs)
|
||||
|
||||
# Increment the current Leo package version number by 1.
|
||||
#
|
||||
# 1. Print out the Leo.toml file.
|
||||
# 2. Search for a line with the word "version".
|
||||
# 3. Isolate that into a single line.
|
||||
# 4. Split the line from the '=' sign and keep the right-hand side.
|
||||
# 5. Remove the quotes around the version number.
|
||||
# 6. Trim any excess whitespace.
|
||||
# 7. Increment the version number by 1 (on the semver patch).
|
||||
#
|
||||
# https://stackoverflow.com/questions/8653126/how-to-increment-version-number-in-a-shell-script
|
||||
export UPDATED=$(cat Leo.toml \
|
||||
| grep version \
|
||||
| head -1 \
|
||||
| awk -F= '{ print $2 }' \
|
||||
| sed 's/[",]//g' \
|
||||
| xargs \
|
||||
| awk -F. -v OFS=. 'NF==1{print ++$NF}; NF>1{if(length($NF+1)>length($NF))$(NF-1)++; $NF=sprintf("%0*d", length($NF), ($NF+1)%(10^length($NF))); print}')
|
||||
|
||||
# Write the updated Leo package version number to the Leo.toml file.
|
||||
export TOML=$(cat Leo.toml | sed "s/$CURRENT/$UPDATED/g")
|
||||
echo "$TOML" > Leo.toml
|
||||
|
||||
# Run the package to confirm the manifest remains well-formed.
|
||||
$LEO run
|
||||
|
||||
# Publish the package to Aleo.pm
|
||||
$LEO publish
|
||||
|
||||
# Logout
|
||||
$LEO logout
|
Binary file not shown.
Before Width: | Height: | Size: 29 KiB |
@ -1 +1 @@
|
||||
v1.2.2
|
||||
v1.2.3
|
||||
|
70
.travis.yml
70
.travis.yml
@ -1,70 +0,0 @@
|
||||
language: rust
|
||||
|
||||
before_install:
|
||||
- set -e
|
||||
- export SCCACHE_CACHE_SIZE=200M
|
||||
- export SCCACHE_DIR="$TRAVIS_HOME/.cache/sccache"
|
||||
- mkdir "$TRAVIS_HOME/.bin"
|
||||
- wget https://github.com/mozilla/sccache/releases/download/0.2.13/sccache-0.2.13-x86_64-unknown-linux-musl.tar.gz
|
||||
- tar -C "$TRAVIS_HOME/.bin" -xvf sccache-0.2.13-x86_64-unknown-linux-musl.tar.gz
|
||||
- mv $TRAVIS_HOME/.bin/sccache-0.2.13-x86_64-unknown-linux-musl/sccache $TRAVIS_HOME/.bin/sccache
|
||||
- export PATH="$PATH:$TRAVIS_HOME/.bin"
|
||||
- export RUSTC_WRAPPER="sccache"
|
||||
- |
|
||||
declare -r SSH_FILE="$(mktemp -u $HOME/.ssh/XXXXX)"
|
||||
openssl aes-256-cbc -K $encrypted_beefc4a47cdc_key -iv $encrypted_beefc4a47cdc_iv -in .travis/travis-snarkvm.enc -out $SSH_FILE -d
|
||||
chmod 600 "$SSH_FILE" \
|
||||
&& printf "%s\n" \
|
||||
"Host github.com" \
|
||||
" IdentityFile $SSH_FILE" \
|
||||
" LogLevel ERROR" >> ~/.ssh/config
|
||||
- git clone --progress --verbose git@github.com:AleoHQ/snarkOS.git
|
||||
- mv snarkOS ..
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $TRAVIS_HOME/.cache/sccache
|
||||
- $TRAVIS_HOME/.cargo
|
||||
|
||||
# See https://levans.fr/rust_travis_cache.html
|
||||
before_cache:
|
||||
- rm -rf "$TRAVIS_HOME/.cargo/registry"
|
||||
|
||||
after_script:
|
||||
- (sccache -s||true)
|
||||
- set +e
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
include:
|
||||
- rust: stable
|
||||
env: TEST_COVERAGE=1
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libcurl4-openssl-dev
|
||||
- libelf-dev
|
||||
- libdw-dev
|
||||
- cmake
|
||||
- gcc
|
||||
- binutils-dev
|
||||
- libiberty-dev
|
||||
script:
|
||||
- cargo test --all
|
||||
after_success:
|
||||
- wget https://github.com/SimonKagstrom/kcov/archive/master.tar.gz
|
||||
- tar xzf master.tar.gz && cd kcov-master
|
||||
- mkdir build && cd build && cmake .. && make && sudo make install
|
||||
- cd ../.. && rm -rf kcov-master
|
||||
- for file in target/debug/deps/*-*; do if [[ "$file" != *\.* ]]; then mkdir -p "target/cov/$(basename $file)"; kcov --exclude-pattern=/.cargo,/usr/lib --verify "target/cov/$(basename $file)" "$file"; fi done
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
- echo "Uploaded code coverage"
|
||||
- rust: nightly-2020-03-18
|
||||
install:
|
||||
- rustup component add rustfmt
|
||||
script:
|
||||
- cargo fmt -- --check
|
||||
- cargo test --all
|
||||
|
||||
script:
|
||||
- echo "leo"
|
Binary file not shown.
853
Cargo.lock
generated
853
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
46
Cargo.toml
46
Cargo.toml
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "leo-lang"
|
||||
version = "1.2.2"
|
||||
version = "1.2.3"
|
||||
authors = [ "The Aleo Team <hello@aleo.org>" ]
|
||||
description = "The Leo programming language"
|
||||
homepage = "https://aleo.org"
|
||||
@ -30,64 +30,65 @@ members = [
|
||||
"ast",
|
||||
"compiler",
|
||||
"gadgets",
|
||||
"grammar",
|
||||
"imports",
|
||||
"input",
|
||||
"linter",
|
||||
"package",
|
||||
"parser",
|
||||
"state",
|
||||
"synthesizer",
|
||||
]
|
||||
|
||||
[dependencies.leo-ast]
|
||||
path = "./ast"
|
||||
version = "1.2.2"
|
||||
version = "1.2.3"
|
||||
|
||||
[dependencies.leo-compiler]
|
||||
path = "./compiler"
|
||||
version = "1.2.2"
|
||||
version = "1.2.3"
|
||||
|
||||
[dependencies.leo-gadgets]
|
||||
path = "./gadgets"
|
||||
version = "1.2.2"
|
||||
version = "1.2.3"
|
||||
|
||||
[dependencies.leo-imports]
|
||||
path = "./imports"
|
||||
version = "1.2.2"
|
||||
version = "1.2.3"
|
||||
|
||||
[dependencies.leo-input]
|
||||
path = "./input"
|
||||
version = "1.2.2"
|
||||
version = "1.2.3"
|
||||
|
||||
[dependencies.leo-package]
|
||||
path = "./package"
|
||||
version = "1.2.2"
|
||||
version = "1.2.3"
|
||||
|
||||
[dependencies.leo-state]
|
||||
path = "./state"
|
||||
version = "1.2.2"
|
||||
version = "1.2.3"
|
||||
|
||||
[dependencies.leo-synthesizer]
|
||||
path = "./synthesizer"
|
||||
version = "1.2.3"
|
||||
|
||||
[dependencies.snarkvm-algorithms]
|
||||
version = "0.0.4"
|
||||
default-features = false
|
||||
version = "0.2.0"
|
||||
#default-features = false
|
||||
|
||||
[dependencies.snarkvm-curves]
|
||||
version = "0.0.4"
|
||||
default-features = false
|
||||
|
||||
[dependencies.snarkvm-errors]
|
||||
version = "0.0.4"
|
||||
version = "0.2.0"
|
||||
default-features = false
|
||||
|
||||
[dependencies.snarkvm-gadgets]
|
||||
version = "0.0.4"
|
||||
version = "0.2.0"
|
||||
default-features = false
|
||||
|
||||
[dependencies.snarkvm-models]
|
||||
version = "0.0.4"
|
||||
[dependencies.snarkvm-r1cs]
|
||||
version = "0.2.0"
|
||||
default-features = false
|
||||
|
||||
[dependencies.snarkvm-utilities]
|
||||
version = "0.0.4"
|
||||
version = "0.2.0"
|
||||
|
||||
[dependencies.anyhow]
|
||||
version = "1.0"
|
||||
@ -116,11 +117,8 @@ version = "1.4.0"
|
||||
[dependencies.notify]
|
||||
version = "4.0.15"
|
||||
|
||||
[dependencies.num-bigint]
|
||||
version = "0.3"
|
||||
|
||||
[dependencies.rand]
|
||||
version = "0.7"
|
||||
version = "0.8"
|
||||
|
||||
[dependencies.rand_core]
|
||||
version = "0.6.2"
|
||||
|
@ -1,5 +1,5 @@
|
||||
<p align="center">
|
||||
<img width="1412" src=".resources/banner.png">
|
||||
<img width="1412" src="https://cdn.aleo.org/leo/banner.png">
|
||||
</p>
|
||||
|
||||
<h1 align="center">The Leo Programming Language</h1>
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "leo-asg"
|
||||
version = "1.2.2"
|
||||
version = "1.2.3"
|
||||
authors = [ "The Aleo Team <hello@aleo.org>" ]
|
||||
description = "ASG of the Leo programming language"
|
||||
homepage = "https://aleo.org"
|
||||
@ -30,12 +30,12 @@ version = "1.6"
|
||||
version = "1.0"
|
||||
|
||||
[dependencies.leo-ast]
|
||||
version = "1.2.2"
|
||||
version = "1.2.3"
|
||||
path = "../ast"
|
||||
|
||||
[dependencies.leo-grammar]
|
||||
version = "1.2.2"
|
||||
path = "../grammar"
|
||||
[dependencies.leo-parser]
|
||||
version = "1.2.3"
|
||||
path = "../parser"
|
||||
|
||||
[dependencies.num-bigint]
|
||||
version = "0.3"
|
||||
|
@ -188,8 +188,30 @@ impl ConstInt {
|
||||
|
||||
const_int_map!(value_negate, x, x.checked_neg()?);
|
||||
|
||||
const_int_map!(value_bit_negate, x, !x);
|
||||
|
||||
const_int_op!(to_usize, Option<usize>, x, (*x).try_into().ok());
|
||||
|
||||
const_int_op!(to_u128, u128, x, *x as u128);
|
||||
|
||||
const_int_op!(to_u64, u64, x, *x as u64);
|
||||
|
||||
const_int_op!(to_u32, u32, x, *x as u32);
|
||||
|
||||
const_int_op!(to_u16, u16, x, *x as u16);
|
||||
|
||||
const_int_op!(to_u8, u8, x, *x as u8);
|
||||
|
||||
const_int_op!(to_i128, i128, x, *x as i128);
|
||||
|
||||
const_int_op!(to_i64, i64, x, *x as i64);
|
||||
|
||||
const_int_op!(to_i32, i32, x, *x as i32);
|
||||
|
||||
const_int_op!(to_i16, i16, x, *x as i16);
|
||||
|
||||
const_int_op!(to_i8, i8, x, *x as i8);
|
||||
|
||||
const_int_op!(to_string, String, x, (*x).to_string());
|
||||
|
||||
const_int_bimap!(value_add, x, y, x.checked_add(*y)?);
|
||||
@ -226,6 +248,21 @@ impl ConstInt {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cast_to(&self, target: &IntegerType) -> ConstInt {
|
||||
match target {
|
||||
IntegerType::I8 => ConstInt::I8(self.to_i8()),
|
||||
IntegerType::I16 => ConstInt::I16(self.to_i16()),
|
||||
IntegerType::I32 => ConstInt::I32(self.to_i32()),
|
||||
IntegerType::I64 => ConstInt::I64(self.to_i64()),
|
||||
IntegerType::I128 => ConstInt::I128(self.to_i128()),
|
||||
IntegerType::U8 => ConstInt::U8(self.to_u8()),
|
||||
IntegerType::U16 => ConstInt::U16(self.to_u16()),
|
||||
IntegerType::U32 => ConstInt::U32(self.to_u32()),
|
||||
IntegerType::U64 => ConstInt::U64(self.to_u64()),
|
||||
IntegerType::U128 => ConstInt::U128(self.to_u128()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_type<'a>(&self) -> Type<'a> {
|
||||
Type::Integer(self.get_int_type())
|
||||
}
|
||||
|
@ -17,14 +17,11 @@
|
||||
//! 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;
|
||||
use leo_ast::{FormattedError, LeoError};
|
||||
use leo_parser::SyntaxError;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum AsgConvertError {
|
||||
#[error("{}", _0)]
|
||||
AstError(#[from] AstError),
|
||||
|
||||
#[error("{}", _0)]
|
||||
Error(#[from] FormattedError),
|
||||
|
||||
@ -35,12 +32,32 @@ pub enum AsgConvertError {
|
||||
InternalError(String),
|
||||
|
||||
#[error("{}", _0)]
|
||||
ParserError(#[from] ParserError),
|
||||
SyntaxError(#[from] SyntaxError),
|
||||
}
|
||||
|
||||
impl LeoError for AsgConvertError {
|
||||
fn get_path(&self) -> Option<&str> {
|
||||
match self {
|
||||
AsgConvertError::Error(error) => error.get_path(),
|
||||
AsgConvertError::SyntaxError(error) => error.get_path(),
|
||||
AsgConvertError::ImportError(error) => error.get_path(),
|
||||
AsgConvertError::InternalError(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn set_path(&mut self, path: &str, contents: &[String]) {
|
||||
match self {
|
||||
AsgConvertError::Error(error) => error.set_path(path, contents),
|
||||
AsgConvertError::SyntaxError(error) => error.set_path(path, contents),
|
||||
AsgConvertError::ImportError(error) => error.set_path(path, contents),
|
||||
AsgConvertError::InternalError(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AsgConvertError {
|
||||
fn new_from_span(message: String, span: &Span) -> Self {
|
||||
AsgConvertError::Error(FormattedError::new_from_span(message, span.clone()))
|
||||
AsgConvertError::Error(FormattedError::new_from_span(message, span))
|
||||
}
|
||||
|
||||
pub fn unresolved_circuit(name: &str, span: &Span) -> Self {
|
||||
@ -227,6 +244,10 @@ impl AsgConvertError {
|
||||
Self::new_from_span(format!("failed to parse int value '{}'", value), span)
|
||||
}
|
||||
|
||||
pub fn unsigned_negation(span: &Span) -> Self {
|
||||
Self::new_from_span("cannot negate unsigned integer".to_string(), span)
|
||||
}
|
||||
|
||||
pub fn immutable_assignment(name: &str, span: &Span) -> Self {
|
||||
Self::new_from_span(format!("illegal assignment to immutable variable '{}'", name), span)
|
||||
}
|
||||
@ -256,6 +277,14 @@ impl AsgConvertError {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn call_test_function(span: &Span) -> Self {
|
||||
Self::new_from_span("cannot call test function".to_string(), span)
|
||||
}
|
||||
|
||||
pub fn circuit_test_function(span: &Span) -> Self {
|
||||
Self::new_from_span("cannot have test function as member of circuit".to_string(), span)
|
||||
}
|
||||
|
||||
pub fn parse_index_error() -> Self {
|
||||
AsgConvertError::InternalError("failed to parse index".to_string())
|
||||
}
|
||||
|
@ -114,7 +114,28 @@ impl<'a> FromAst<'a, leo_ast::ArrayInlineExpression> for ArrayInlineExpression<'
|
||||
}
|
||||
};
|
||||
|
||||
// If we still don't know the type iterate through processing to get a type.
|
||||
// Once we encouter the type break the loop so we process as little as possible.
|
||||
if expected_item.is_none() {
|
||||
for expr in value.elements.iter() {
|
||||
expected_item = match expr {
|
||||
SpreadOrExpression::Expression(e) => {
|
||||
match <&Expression<'a>>::from_ast(scope, e, expected_item.clone()) {
|
||||
Ok(expr) => expr.get_type().map(Type::partial),
|
||||
Err(_) => continue,
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
|
||||
if expected_item.is_some() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut len = 0;
|
||||
|
||||
let output = ArrayInlineExpression {
|
||||
parent: Cell::new(None),
|
||||
span: Some(value.span.clone()),
|
||||
|
@ -109,7 +109,7 @@ impl<'a> FromAst<'a, leo_ast::CallExpression> for CallExpression<'a> {
|
||||
return Err(AsgConvertError::unexpected_type(
|
||||
"circuit",
|
||||
type_.map(|x| x.to_string()).as_deref(),
|
||||
&span,
|
||||
span,
|
||||
));
|
||||
}
|
||||
};
|
||||
@ -117,26 +117,26 @@ impl<'a> FromAst<'a, leo_ast::CallExpression> for CallExpression<'a> {
|
||||
let member = circuit.members.borrow();
|
||||
let member = member
|
||||
.get(&name.name)
|
||||
.ok_or_else(|| AsgConvertError::unresolved_circuit_member(&circuit_name, &name.name, &span))?;
|
||||
.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,
|
||||
span,
|
||||
));
|
||||
} else if body.qualifier == FunctionQualifier::MutSelfRef && !target.is_mut_ref() {
|
||||
return Err(AsgConvertError::circuit_member_mut_call_invalid(
|
||||
&circuit_name,
|
||||
&name.name,
|
||||
&span,
|
||||
span,
|
||||
));
|
||||
}
|
||||
(Some(target), *body)
|
||||
}
|
||||
CircuitMember::Variable(_) => {
|
||||
return Err(AsgConvertError::circuit_variable_call(&circuit_name, &name.name, &span));
|
||||
return Err(AsgConvertError::circuit_variable_call(&circuit_name, &name.name, span));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -150,27 +150,27 @@ impl<'a> FromAst<'a, leo_ast::CallExpression> for CallExpression<'a> {
|
||||
.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));
|
||||
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))?;
|
||||
.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,
|
||||
span,
|
||||
));
|
||||
}
|
||||
(None, *body)
|
||||
}
|
||||
CircuitMember::Variable(_) => {
|
||||
return Err(AsgConvertError::circuit_variable_call(&circuit_name, &name.name, &span));
|
||||
return Err(AsgConvertError::circuit_variable_call(&circuit_name, &name.name, span));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -206,12 +206,15 @@ impl<'a> FromAst<'a, leo_ast::CallExpression> for CallExpression<'a> {
|
||||
let argument = argument.get().borrow();
|
||||
let converted = <&Expression<'a>>::from_ast(scope, expr, Some(argument.type_.clone().partial()))?;
|
||||
if argument.const_ && !converted.is_consty() {
|
||||
return Err(AsgConvertError::unexpected_nonconst(&expr.span()));
|
||||
return Err(AsgConvertError::unexpected_nonconst(expr.span()));
|
||||
}
|
||||
Ok(Cell::new(converted))
|
||||
})
|
||||
.collect::<Result<Vec<_>, AsgConvertError>>()?;
|
||||
|
||||
if function.is_test() {
|
||||
return Err(AsgConvertError::call_test_function(&value.span));
|
||||
}
|
||||
Ok(CallExpression {
|
||||
parent: Cell::new(None),
|
||||
span: Some(value.span.clone()),
|
||||
|
109
asg/src/expression/cast.rs
Normal file
109
asg/src/expression/cast.rs
Normal file
@ -0,0 +1,109 @@
|
||||
// Copyright (C) 2019-2021 Aleo Systems Inc.
|
||||
// This file is part of the Leo library.
|
||||
|
||||
// The Leo library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// The Leo library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{AsgConvertError, ConstValue, Expression, ExpressionNode, FromAst, Node, PartialType, Scope, Span, Type};
|
||||
pub use leo_ast::UnaryOperation;
|
||||
|
||||
use std::cell::Cell;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct CastExpression<'a> {
|
||||
pub parent: Cell<Option<&'a Expression<'a>>>,
|
||||
pub span: Option<Span>,
|
||||
pub inner: Cell<&'a Expression<'a>>,
|
||||
pub target_type: Type<'a>,
|
||||
}
|
||||
|
||||
impl<'a> Node for CastExpression<'a> {
|
||||
fn span(&self) -> Option<&Span> {
|
||||
self.span.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ExpressionNode<'a> for CastExpression<'a> {
|
||||
fn set_parent(&self, parent: &'a Expression<'a>) {
|
||||
self.parent.replace(Some(parent));
|
||||
}
|
||||
|
||||
fn get_parent(&self) -> Option<&'a Expression<'a>> {
|
||||
self.parent.get()
|
||||
}
|
||||
|
||||
fn enforce_parents(&self, expr: &'a Expression<'a>) {
|
||||
self.inner.get().set_parent(expr);
|
||||
}
|
||||
|
||||
fn get_type(&self) -> Option<Type<'a>> {
|
||||
Some(self.target_type.clone())
|
||||
}
|
||||
|
||||
fn is_mut_ref(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn const_value(&self) -> Option<ConstValue> {
|
||||
let value = self.inner.get().const_value()?;
|
||||
match value {
|
||||
ConstValue::Int(int) => match &self.target_type {
|
||||
Type::Integer(target) => Some(ConstValue::Int(int.cast_to(target))),
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_consty(&self) -> bool {
|
||||
self.inner.get().is_consty()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> FromAst<'a, leo_ast::CastExpression> for CastExpression<'a> {
|
||||
fn from_ast(
|
||||
scope: &'a Scope<'a>,
|
||||
value: &leo_ast::CastExpression,
|
||||
expected_type: Option<PartialType<'a>>,
|
||||
) -> Result<CastExpression<'a>, AsgConvertError> {
|
||||
let target_type = scope.resolve_ast_type(&value.target_type)?;
|
||||
if let Some(expected_type) = &expected_type {
|
||||
if !expected_type.matches(&target_type) {
|
||||
return Err(AsgConvertError::unexpected_type(
|
||||
&expected_type.to_string(),
|
||||
Some(&target_type.to_string()),
|
||||
&value.span,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
let inner = <&Expression<'a>>::from_ast(scope, &*value.inner, None)?;
|
||||
|
||||
Ok(CastExpression {
|
||||
parent: Cell::new(None),
|
||||
span: Some(value.span.clone()),
|
||||
inner: Cell::new(inner),
|
||||
target_type,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Into<leo_ast::CastExpression> for &CastExpression<'a> {
|
||||
fn into(self) -> leo_ast::CastExpression {
|
||||
leo_ast::CastExpression {
|
||||
target_type: (&self.target_type).into(),
|
||||
inner: Box::new(self.inner.get().into()),
|
||||
span: self.span.clone().unwrap_or_default(),
|
||||
}
|
||||
}
|
||||
}
|
@ -99,10 +99,10 @@ impl<'a> FromAst<'a, leo_ast::CircuitInitExpression> for CircuitInitExpression<'
|
||||
));
|
||||
}
|
||||
}
|
||||
let members: IndexMap<&String, (&Identifier, &leo_ast::Expression)> = value
|
||||
let members: IndexMap<&String, (&Identifier, Option<&leo_ast::Expression>)> = value
|
||||
.members
|
||||
.iter()
|
||||
.map(|x| (&x.identifier.name, (&x.identifier, &x.expression)))
|
||||
.map(|x| (&x.identifier.name, (&x.identifier, x.expression.as_ref())))
|
||||
.collect();
|
||||
|
||||
let mut values: Vec<(Identifier, Cell<&'a Expression<'a>>)> = vec![];
|
||||
@ -125,7 +125,15 @@ impl<'a> FromAst<'a, leo_ast::CircuitInitExpression> for CircuitInitExpression<'
|
||||
continue;
|
||||
};
|
||||
if let Some((identifier, receiver)) = members.get(&name) {
|
||||
let received = <&Expression<'a>>::from_ast(scope, *receiver, Some(type_.partial()))?;
|
||||
let received = if let Some(receiver) = *receiver {
|
||||
<&Expression<'a>>::from_ast(scope, receiver, Some(type_.partial()))?
|
||||
} else {
|
||||
<&Expression<'a>>::from_ast(
|
||||
scope,
|
||||
&leo_ast::Expression::Identifier((*identifier).clone()),
|
||||
Some(type_.partial()),
|
||||
)?
|
||||
};
|
||||
values.push(((*identifier).clone(), Cell::new(received)));
|
||||
} else {
|
||||
return Err(AsgConvertError::missing_circuit_member(
|
||||
@ -165,7 +173,7 @@ impl<'a> Into<leo_ast::CircuitInitExpression> for &CircuitInitExpression<'a> {
|
||||
.iter()
|
||||
.map(|(name, value)| leo_ast::CircuitImpliedVariableDefinition {
|
||||
identifier: name.clone(),
|
||||
expression: value.get().into(),
|
||||
expression: Some(value.get().into()),
|
||||
})
|
||||
.collect(),
|
||||
span: self.span.clone().unwrap_or_default(),
|
||||
|
@ -62,6 +62,9 @@ pub use unary::*;
|
||||
mod variable_ref;
|
||||
pub use variable_ref::*;
|
||||
|
||||
mod cast;
|
||||
pub use cast::*;
|
||||
|
||||
use crate::{AsgConvertError, ConstValue, FromAst, Node, PartialType, Scope, Span, Type};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -71,6 +74,7 @@ pub enum Expression<'a> {
|
||||
Binary(BinaryExpression<'a>),
|
||||
Unary(UnaryExpression<'a>),
|
||||
Ternary(TernaryExpression<'a>),
|
||||
Cast(CastExpression<'a>),
|
||||
|
||||
ArrayInline(ArrayInlineExpression<'a>),
|
||||
ArrayInit(ArrayInitExpression<'a>),
|
||||
@ -95,6 +99,7 @@ impl<'a> Node for Expression<'a> {
|
||||
Binary(x) => x.span(),
|
||||
Unary(x) => x.span(),
|
||||
Ternary(x) => x.span(),
|
||||
Cast(x) => x.span(),
|
||||
ArrayInline(x) => x.span(),
|
||||
ArrayInit(x) => x.span(),
|
||||
ArrayAccess(x) => x.span(),
|
||||
@ -128,6 +133,7 @@ impl<'a> ExpressionNode<'a> for Expression<'a> {
|
||||
Binary(x) => x.set_parent(parent),
|
||||
Unary(x) => x.set_parent(parent),
|
||||
Ternary(x) => x.set_parent(parent),
|
||||
Cast(x) => x.set_parent(parent),
|
||||
ArrayInline(x) => x.set_parent(parent),
|
||||
ArrayInit(x) => x.set_parent(parent),
|
||||
ArrayAccess(x) => x.set_parent(parent),
|
||||
@ -148,6 +154,7 @@ impl<'a> ExpressionNode<'a> for Expression<'a> {
|
||||
Binary(x) => x.get_parent(),
|
||||
Unary(x) => x.get_parent(),
|
||||
Ternary(x) => x.get_parent(),
|
||||
Cast(x) => x.get_parent(),
|
||||
ArrayInline(x) => x.get_parent(),
|
||||
ArrayInit(x) => x.get_parent(),
|
||||
ArrayAccess(x) => x.get_parent(),
|
||||
@ -168,6 +175,7 @@ impl<'a> ExpressionNode<'a> for Expression<'a> {
|
||||
Binary(x) => x.enforce_parents(expr),
|
||||
Unary(x) => x.enforce_parents(expr),
|
||||
Ternary(x) => x.enforce_parents(expr),
|
||||
Cast(x) => x.enforce_parents(expr),
|
||||
ArrayInline(x) => x.enforce_parents(expr),
|
||||
ArrayInit(x) => x.enforce_parents(expr),
|
||||
ArrayAccess(x) => x.enforce_parents(expr),
|
||||
@ -188,6 +196,7 @@ impl<'a> ExpressionNode<'a> for Expression<'a> {
|
||||
Binary(x) => x.get_type(),
|
||||
Unary(x) => x.get_type(),
|
||||
Ternary(x) => x.get_type(),
|
||||
Cast(x) => x.get_type(),
|
||||
ArrayInline(x) => x.get_type(),
|
||||
ArrayInit(x) => x.get_type(),
|
||||
ArrayAccess(x) => x.get_type(),
|
||||
@ -208,6 +217,7 @@ impl<'a> ExpressionNode<'a> for Expression<'a> {
|
||||
Binary(x) => x.is_mut_ref(),
|
||||
Unary(x) => x.is_mut_ref(),
|
||||
Ternary(x) => x.is_mut_ref(),
|
||||
Cast(x) => x.is_mut_ref(),
|
||||
ArrayInline(x) => x.is_mut_ref(),
|
||||
ArrayInit(x) => x.is_mut_ref(),
|
||||
ArrayAccess(x) => x.is_mut_ref(),
|
||||
@ -228,6 +238,7 @@ impl<'a> ExpressionNode<'a> for Expression<'a> {
|
||||
Binary(x) => x.const_value(),
|
||||
Unary(x) => x.const_value(),
|
||||
Ternary(x) => x.const_value(),
|
||||
Cast(x) => x.const_value(),
|
||||
ArrayInline(x) => x.const_value(),
|
||||
ArrayInit(x) => x.const_value(),
|
||||
ArrayAccess(x) => x.const_value(),
|
||||
@ -248,6 +259,7 @@ impl<'a> ExpressionNode<'a> for Expression<'a> {
|
||||
Binary(x) => x.is_consty(),
|
||||
Unary(x) => x.is_consty(),
|
||||
Ternary(x) => x.is_consty(),
|
||||
Cast(x) => x.is_consty(),
|
||||
ArrayInline(x) => x.is_consty(),
|
||||
ArrayInit(x) => x.is_consty(),
|
||||
ArrayAccess(x) => x.is_consty(),
|
||||
@ -281,6 +293,9 @@ impl<'a> FromAst<'a, leo_ast::Expression> for &'a Expression<'a> {
|
||||
Ternary(conditional) => scope.alloc_expression(
|
||||
TernaryExpression::from_ast(scope, conditional, expected_type).map(Expression::Ternary)?,
|
||||
),
|
||||
Cast(cast) => {
|
||||
scope.alloc_expression(CastExpression::from_ast(scope, cast, expected_type).map(Expression::Cast)?)
|
||||
}
|
||||
|
||||
ArrayInline(array_inline) => scope.alloc_expression(
|
||||
ArrayInlineExpression::from_ast(scope, array_inline, expected_type).map(Expression::ArrayInline)?,
|
||||
@ -333,6 +348,7 @@ impl<'a> Into<leo_ast::Expression> for &Expression<'a> {
|
||||
Binary(x) => leo_ast::Expression::Binary(x.into()),
|
||||
Unary(x) => leo_ast::Expression::Unary(x.into()),
|
||||
Ternary(x) => leo_ast::Expression::Ternary(x.into()),
|
||||
Cast(x) => leo_ast::Expression::Cast(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()),
|
||||
|
@ -69,6 +69,10 @@ impl<'a> ExpressionNode<'a> for UnaryExpression<'a> {
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
UnaryOperation::BitNot => match inner {
|
||||
ConstValue::Int(value) => Some(ConstValue::Int(value.value_bit_negate()?)),
|
||||
_ => None,
|
||||
},
|
||||
}
|
||||
} else {
|
||||
None
|
||||
@ -110,16 +114,37 @@ impl<'a> FromAst<'a, leo_ast::UnaryExpression> for UnaryExpression<'a> {
|
||||
));
|
||||
}
|
||||
},
|
||||
UnaryOperation::BitNot => match expected_type.map(|x| x.full()).flatten() {
|
||||
Some(type_ @ Type::Integer(_)) => Some(type_),
|
||||
None => None,
|
||||
Some(type_) => {
|
||||
return Err(AsgConvertError::unexpected_type(
|
||||
&type_.to_string(),
|
||||
Some("integer"),
|
||||
&value.span,
|
||||
));
|
||||
}
|
||||
},
|
||||
};
|
||||
let expr = <&Expression<'a>>::from_ast(scope, &*value.inner, expected_type.map(Into::into))?;
|
||||
|
||||
if matches!(value.op, UnaryOperation::Negate) {
|
||||
let is_expr_unsigned = expr
|
||||
.get_type()
|
||||
.map(|x| match x {
|
||||
Type::Integer(x) => !x.is_signed(),
|
||||
_ => false,
|
||||
})
|
||||
.unwrap_or(false);
|
||||
if is_expr_unsigned {
|
||||
return Err(AsgConvertError::unsigned_negation(&value.span));
|
||||
}
|
||||
}
|
||||
Ok(UnaryExpression {
|
||||
parent: Cell::new(None),
|
||||
span: Some(value.span.clone()),
|
||||
operation: value.op.clone(),
|
||||
inner: Cell::new(<&Expression<'a>>::from_ast(
|
||||
scope,
|
||||
&*value.inner,
|
||||
expected_type.map(Into::into),
|
||||
)?),
|
||||
inner: Cell::new(expr),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -76,8 +76,6 @@ pub use context::*;
|
||||
|
||||
pub use leo_ast::{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.
|
||||
@ -92,14 +90,14 @@ pub struct Asg<'a> {
|
||||
|
||||
impl<'a> Asg<'a> {
|
||||
/// Creates a new ASG from a given AST and import resolver.
|
||||
pub fn new<T: ImportResolver<'a>>(
|
||||
pub fn new<T: ImportResolver<'a>, Y: AsRef<leo_ast::Program>>(
|
||||
context: AsgContext<'a>,
|
||||
ast: &Ast,
|
||||
ast: Y,
|
||||
resolver: &mut T,
|
||||
) -> Result<Self, AsgConvertError> {
|
||||
Ok(Self {
|
||||
context,
|
||||
asg: InternalProgram::new(context, &ast.as_repr(), resolver)?,
|
||||
asg: InternalProgram::new(context, ast.as_ref(), resolver)?,
|
||||
})
|
||||
}
|
||||
|
||||
@ -127,10 +125,9 @@ pub fn load_asg<'a, T: ImportResolver<'a>>(
|
||||
resolver: &mut T,
|
||||
) -> Result<Program<'a>, AsgConvertError> {
|
||||
// Parses the Leo file and constructs a grammar ast.
|
||||
let ast = leo_grammar::Grammar::new(&Path::new("input.leo"), content)
|
||||
.map_err(|e| AsgConvertError::InternalError(format!("ast: {:?}", e)))?;
|
||||
let ast = leo_parser::parse_ast("input.leo", content)?;
|
||||
|
||||
InternalProgram::new(context, leo_ast::Ast::new("load_ast", &ast)?.as_repr(), resolver)
|
||||
InternalProgram::new(context, ast.as_repr(), resolver)
|
||||
}
|
||||
|
||||
pub fn new_alloc_context<'a>() -> Arena<ArenaNode<'a>> {
|
||||
|
@ -15,7 +15,7 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::Program;
|
||||
pub use leo_ast::Error as FormattedError;
|
||||
pub use leo_ast::FormattedError;
|
||||
|
||||
pub trait AsgPass {
|
||||
fn do_pass(asg: &Program) -> Result<(), FormattedError>;
|
||||
|
@ -92,6 +92,9 @@ impl<'a> Circuit<'a> {
|
||||
}
|
||||
let asg_function = Function::init(new_scope, function)?;
|
||||
asg_function.circuit.replace(Some(circuit));
|
||||
if asg_function.is_test() {
|
||||
return Err(AsgConvertError::circuit_test_function(&function.identifier.span));
|
||||
}
|
||||
members.insert(function.identifier.name.clone(), CircuitMember::Function(asg_function));
|
||||
}
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ use crate::{
|
||||
Variable,
|
||||
};
|
||||
use indexmap::IndexMap;
|
||||
pub use leo_ast::Annotation;
|
||||
use leo_ast::FunctionInput;
|
||||
|
||||
use std::cell::{Cell, RefCell};
|
||||
@ -52,6 +53,7 @@ pub struct Function<'a> {
|
||||
pub body: Cell<Option<&'a Statement<'a>>>,
|
||||
pub scope: &'a Scope<'a>,
|
||||
pub qualifier: FunctionQualifier,
|
||||
pub annotations: Vec<Annotation>,
|
||||
}
|
||||
|
||||
impl<'a> PartialEq for Function<'a> {
|
||||
@ -126,6 +128,7 @@ impl<'a> Function<'a> {
|
||||
qualifier,
|
||||
scope: new_scope,
|
||||
span: Some(value.span.clone()),
|
||||
annotations: value.annotations.clone(),
|
||||
});
|
||||
function.scope.function.replace(Some(function));
|
||||
|
||||
@ -177,6 +180,10 @@ impl<'a> Function<'a> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn is_test(&self) -> bool {
|
||||
self.annotations.iter().any(|x| x.name.name == "test")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Into<leo_ast::Function> for &Function<'a> {
|
||||
@ -213,6 +220,7 @@ impl<'a> Into<leo_ast::Function> for &Function<'a> {
|
||||
block: body,
|
||||
output: Some((&output).into()),
|
||||
span,
|
||||
annotations: self.annotations.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -45,9 +45,6 @@ pub struct InternalProgram<'a> {
|
||||
/// these should generally not be accessed directly, but through scoped imports
|
||||
pub imported_modules: IndexMap<String, Program<'a>>,
|
||||
|
||||
/// Maps test name => test code block.
|
||||
pub test_functions: IndexMap<String, (&'a Function<'a>, Option<Identifier>)>, // identifier = test input file
|
||||
|
||||
/// Maps function name => function code block.
|
||||
pub functions: IndexMap<String, &'a Function<'a>>,
|
||||
|
||||
@ -248,14 +245,6 @@ impl<'a> InternalProgram<'a> {
|
||||
scope.circuits.borrow_mut().insert(name.name.clone(), asg_circuit);
|
||||
}
|
||||
|
||||
let mut proto_test_functions = IndexMap::new();
|
||||
for (name, test_function) in program.tests.iter() {
|
||||
assert_eq!(name.name, test_function.function.identifier.name);
|
||||
let function = Function::init(scope, &test_function.function)?;
|
||||
|
||||
proto_test_functions.insert(name.name.clone(), function);
|
||||
}
|
||||
|
||||
for (name, function) in program.functions.iter() {
|
||||
assert_eq!(name.name, function.identifier.name);
|
||||
let function = Function::init(scope, function)?;
|
||||
@ -264,16 +253,6 @@ impl<'a> InternalProgram<'a> {
|
||||
}
|
||||
|
||||
// Load concrete definitions.
|
||||
let mut test_functions = IndexMap::new();
|
||||
for (name, test_function) in program.tests.iter() {
|
||||
assert_eq!(name.name, test_function.function.identifier.name);
|
||||
let function = proto_test_functions.get(&name.name).unwrap();
|
||||
|
||||
function.fill_from_ast(&test_function.function)?;
|
||||
|
||||
test_functions.insert(name.name.clone(), (*function, test_function.input_file.clone()));
|
||||
}
|
||||
|
||||
let mut functions = IndexMap::new();
|
||||
for (name, function) in program.functions.iter() {
|
||||
assert_eq!(name.name, function.identifier.name);
|
||||
@ -298,7 +277,6 @@ impl<'a> InternalProgram<'a> {
|
||||
context,
|
||||
id: context.get_id(),
|
||||
name: program.name.clone(),
|
||||
test_functions,
|
||||
functions,
|
||||
circuits,
|
||||
imported_modules: resolved_packages
|
||||
@ -350,7 +328,6 @@ pub fn reform_ast<'a>(program: &Program<'a>) -> leo_ast::Program {
|
||||
|
||||
let mut all_circuits: IndexMap<String, &'a Circuit<'a>> = IndexMap::new();
|
||||
let mut all_functions: IndexMap<String, &'a Function<'a>> = IndexMap::new();
|
||||
let mut all_test_functions: IndexMap<String, (&'a Function<'a>, Option<Identifier>)> = IndexMap::new();
|
||||
let mut identifiers = InternalIdentifierGenerator { next: 0 };
|
||||
for (_, program) in all_programs.into_iter() {
|
||||
for (name, circuit) in program.circuits.iter() {
|
||||
@ -367,11 +344,6 @@ pub fn reform_ast<'a>(program: &Program<'a>) -> leo_ast::Program {
|
||||
function.name.borrow_mut().name = identifier.clone();
|
||||
all_functions.insert(identifier, *function);
|
||||
}
|
||||
for (name, function) in program.test_functions.iter() {
|
||||
let identifier = format!("{}{}", identifiers.next().unwrap(), name);
|
||||
function.0.name.borrow_mut().name = identifier.clone();
|
||||
all_test_functions.insert(identifier, function.clone());
|
||||
}
|
||||
}
|
||||
|
||||
leo_ast::Program {
|
||||
@ -388,15 +360,6 @@ pub fn reform_ast<'a>(program: &Program<'a>) -> leo_ast::Program {
|
||||
})
|
||||
.collect(),
|
||||
expected_input: vec![],
|
||||
tests: all_test_functions
|
||||
.into_iter()
|
||||
.map(|(_, (function, ident))| {
|
||||
(function.name.borrow().clone(), leo_ast::TestFunction {
|
||||
function: function.into(),
|
||||
input_file: ident,
|
||||
})
|
||||
})
|
||||
.collect(),
|
||||
functions: all_functions
|
||||
.into_iter()
|
||||
.map(|(_, function)| (function.name.borrow().clone(), function.into()))
|
||||
@ -424,16 +387,6 @@ impl<'a> Into<leo_ast::Program> for &InternalProgram<'a> {
|
||||
.iter()
|
||||
.map(|(_, function)| (function.name.borrow().clone(), (*function).into()))
|
||||
.collect(),
|
||||
tests: self
|
||||
.test_functions
|
||||
.iter()
|
||||
.map(|(_, function)| {
|
||||
(function.0.name.borrow().clone(), leo_ast::TestFunction {
|
||||
function: function.0.into(),
|
||||
input_file: function.1.clone(),
|
||||
})
|
||||
})
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -47,6 +47,7 @@ impl<'a, T: Monoid, R: MonoidalReducerExpression<'a, T>> MonoidalDirector<'a, T,
|
||||
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::Cast(e) => self.reduce_cast_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),
|
||||
@ -131,6 +132,12 @@ impl<'a, T: Monoid, R: MonoidalReducerExpression<'a, T>> MonoidalDirector<'a, T,
|
||||
.reduce_ternary_expression(input, condition, if_true, if_false)
|
||||
}
|
||||
|
||||
pub fn reduce_cast_expression(&mut self, input: &CastExpression<'a>) -> T {
|
||||
let inner = self.reduce_expression(input.inner.get());
|
||||
|
||||
self.reducer.reduce_cast_expression(input, inner)
|
||||
}
|
||||
|
||||
pub fn reduce_constant(&mut self, input: &Constant<'a>) -> T {
|
||||
self.reducer.reduce_constant(input)
|
||||
}
|
||||
@ -299,15 +306,10 @@ impl<'a, T: Monoid, R: MonoidalReducerProgram<'a, T>> MonoidalDirector<'a, T, R>
|
||||
.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)
|
||||
.reduce_program(&input, imported_modules, functions, circuits)
|
||||
}
|
||||
}
|
||||
|
@ -64,6 +64,10 @@ pub trait MonoidalReducerExpression<'a, T: Monoid> {
|
||||
condition.append(if_true).append(if_false)
|
||||
}
|
||||
|
||||
fn reduce_cast_expression(&mut self, input: &CastExpression<'a>, inner: T) -> T {
|
||||
inner
|
||||
}
|
||||
|
||||
fn reduce_constant(&mut self, input: &Constant<'a>) -> T {
|
||||
T::default()
|
||||
}
|
||||
@ -157,13 +161,11 @@ pub trait MonoidalReducerProgram<'a, T: Monoid>: MonoidalReducerStatement<'a, T>
|
||||
&mut self,
|
||||
input: &InternalProgram,
|
||||
imported_modules: Vec<T>,
|
||||
test_functions: Vec<T>,
|
||||
functions: Vec<T>,
|
||||
circuits: Vec<T>,
|
||||
) -> 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())
|
||||
}
|
||||
|
@ -72,6 +72,10 @@ pub trait ExpressionVisitor<'a> {
|
||||
Default::default()
|
||||
}
|
||||
|
||||
fn visit_cast_expression(&mut self, input: &CastExpression<'a>) -> VisitResult {
|
||||
Default::default()
|
||||
}
|
||||
|
||||
fn visit_constant(&mut self, input: &Constant<'a>) -> VisitResult {
|
||||
Default::default()
|
||||
}
|
||||
|
@ -60,6 +60,7 @@ impl<'a, R: ExpressionVisitor<'a>> VisitorDirector<'a, R> {
|
||||
Expression::CircuitAccess(e) => self.visit_circuit_access(e),
|
||||
Expression::CircuitInit(e) => self.visit_circuit_init(e),
|
||||
Expression::Ternary(e) => self.visit_ternary_expression(e),
|
||||
Expression::Cast(e) => self.visit_cast_expression(e),
|
||||
Expression::Constant(e) => self.visit_constant(e),
|
||||
Expression::TupleAccess(e) => self.visit_tuple_access(e),
|
||||
Expression::TupleInit(e) => self.visit_tuple_init(e),
|
||||
@ -71,10 +72,7 @@ impl<'a, R: ExpressionVisitor<'a>> VisitorDirector<'a, R> {
|
||||
}
|
||||
|
||||
fn visit_opt_expression(&mut self, input: &Cell<Option<&'a Expression<'a>>>) -> ConcreteVisitResult {
|
||||
let interior = match input.get() {
|
||||
Some(expr) => Some(Cell::new(expr)),
|
||||
None => None,
|
||||
};
|
||||
let interior = input.get().map(Cell::new);
|
||||
if let Some(interior) = interior.as_ref() {
|
||||
let result = self.visit_expression(interior);
|
||||
input.replace(Some(interior.get()));
|
||||
@ -187,6 +185,16 @@ impl<'a, R: ExpressionVisitor<'a>> VisitorDirector<'a, R> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn visit_cast_expression(&mut self, input: &CastExpression<'a>) -> ConcreteVisitResult {
|
||||
match self.visitor.visit_cast_expression(input) {
|
||||
VisitResult::VisitChildren => {
|
||||
self.visit_expression(&input.inner)?;
|
||||
Ok(())
|
||||
}
|
||||
x => x.into(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn visit_constant(&mut self, input: &Constant<'a>) -> ConcreteVisitResult {
|
||||
self.visitor.visit_constant(input).into()
|
||||
}
|
||||
@ -246,10 +254,7 @@ impl<'a, R: StatementVisitor<'a>> VisitorDirector<'a, R> {
|
||||
}
|
||||
|
||||
fn visit_opt_statement(&mut self, input: &Cell<Option<&'a Statement<'a>>>) -> ConcreteVisitResult {
|
||||
let interior = match input.get() {
|
||||
Some(expr) => Some(Cell::new(expr)),
|
||||
None => None,
|
||||
};
|
||||
let interior = input.get().map(Cell::new);
|
||||
if let Some(interior) = interior.as_ref() {
|
||||
let result = self.visit_statement(interior);
|
||||
input.replace(Some(interior.get()));
|
||||
@ -425,9 +430,6 @@ impl<'a, R: ProgramVisitor<'a>> VisitorDirector<'a, R> {
|
||||
for (_, import) in input.imported_modules.iter() {
|
||||
self.visit_program(import)?;
|
||||
}
|
||||
for (_, (function, _)) in input.test_functions.iter() {
|
||||
self.visit_function(function)?;
|
||||
}
|
||||
for (_, function) in input.functions.iter() {
|
||||
self.visit_function(function)?;
|
||||
}
|
||||
|
@ -72,10 +72,10 @@ impl<'a> FromAst<'a, leo_ast::AssignStatement> for &'a Statement<'a> {
|
||||
let variable = if name == "input" {
|
||||
if let Some(function) = scope.resolve_current_function() {
|
||||
if !function.has_input {
|
||||
return Err(AsgConvertError::unresolved_reference(name, span));
|
||||
return Err(AsgConvertError::unresolved_reference(name, &span));
|
||||
}
|
||||
} else {
|
||||
return Err(AsgConvertError::unresolved_reference(name, span));
|
||||
return Err(AsgConvertError::unresolved_reference(name, &span));
|
||||
}
|
||||
if let Some(input) = scope.resolve_input() {
|
||||
input.container
|
||||
@ -87,7 +87,7 @@ impl<'a> FromAst<'a, leo_ast::AssignStatement> for &'a Statement<'a> {
|
||||
} else {
|
||||
scope
|
||||
.resolve_variable(&name)
|
||||
.ok_or_else(|| AsgConvertError::unresolved_reference(name, span))?
|
||||
.ok_or_else(|| AsgConvertError::unresolved_reference(name, &span))?
|
||||
};
|
||||
|
||||
if !variable.borrow().mutable {
|
||||
|
@ -15,15 +15,14 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{AsgConvertError, Expression, FromAst, Node, PartialType, Scope, Span, Statement, Type};
|
||||
use leo_ast::ConsoleFunction as AstConsoleFunction;
|
||||
use leo_ast::{ConsoleFunction as AstConsoleFunction, FormattedStringPart};
|
||||
|
||||
use std::cell::Cell;
|
||||
|
||||
// TODO (protryon): Refactor to not require/depend on span
|
||||
#[derive(Clone)]
|
||||
pub struct FormattedString<'a> {
|
||||
pub string: String,
|
||||
pub containers: Vec<Span>,
|
||||
pub parts: Vec<FormattedStringPart>,
|
||||
pub parameters: Vec<Cell<&'a Expression<'a>>>,
|
||||
pub span: Span,
|
||||
}
|
||||
@ -55,10 +54,15 @@ impl<'a> FromAst<'a, leo_ast::FormattedString> for FormattedString<'a> {
|
||||
value: &leo_ast::FormattedString,
|
||||
_expected_type: Option<PartialType<'a>>,
|
||||
) -> Result<Self, AsgConvertError> {
|
||||
if value.parameters.len() != value.containers.len() {
|
||||
let expected_param_len = value
|
||||
.parts
|
||||
.iter()
|
||||
.filter(|x| matches!(x, FormattedStringPart::Container))
|
||||
.count();
|
||||
if value.parameters.len() != expected_param_len {
|
||||
// + 1 for formatting string as to not confuse user
|
||||
return Err(AsgConvertError::unexpected_call_argument_count(
|
||||
value.containers.len() + 1,
|
||||
expected_param_len + 1,
|
||||
value.parameters.len() + 1,
|
||||
&value.span,
|
||||
));
|
||||
@ -68,8 +72,7 @@ impl<'a> FromAst<'a, leo_ast::FormattedString> for FormattedString<'a> {
|
||||
parameters.push(Cell::new(<&Expression<'a>>::from_ast(scope, parameter, None)?));
|
||||
}
|
||||
Ok(FormattedString {
|
||||
string: value.string.clone(),
|
||||
containers: value.containers.iter().map(|x| x.span.clone()).collect(),
|
||||
parts: value.parts.clone(),
|
||||
parameters,
|
||||
span: value.span.clone(),
|
||||
})
|
||||
@ -79,12 +82,7 @@ impl<'a> FromAst<'a, leo_ast::FormattedString> for FormattedString<'a> {
|
||||
impl<'a> Into<leo_ast::FormattedString> for &FormattedString<'a> {
|
||||
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(),
|
||||
parts: self.parts.clone(),
|
||||
parameters: self.parameters.iter().map(|e| e.get().into()).collect(),
|
||||
span: self.span.clone(),
|
||||
}
|
||||
|
@ -28,7 +28,6 @@ use crate::{
|
||||
Type,
|
||||
Variable,
|
||||
};
|
||||
use leo_ast::{AstError, DeprecatedError};
|
||||
|
||||
use std::cell::{Cell, RefCell};
|
||||
|
||||
@ -90,11 +89,6 @@ impl<'a> FromAst<'a, leo_ast::DefinitionStatement> for &'a Statement<'a> {
|
||||
}
|
||||
|
||||
for (variable, type_) in statement.variable_names.iter().zip(output_types.into_iter()) {
|
||||
if statement.declaration_type == leo_ast::Declare::Const {
|
||||
return Err(AsgConvertError::AstError(AstError::DeprecatedError(
|
||||
DeprecatedError::const_statement(&statement.span),
|
||||
)));
|
||||
}
|
||||
variables.push(&*scope.alloc_variable(RefCell::new(InnerVariable {
|
||||
id: scope.context.get_id(),
|
||||
name: variable.identifier.clone(),
|
||||
|
@ -123,6 +123,10 @@ impl<'a> Type<'a> {
|
||||
pub fn is_unit(&self) -> bool {
|
||||
matches!(self, Type::Tuple(t) if t.is_empty())
|
||||
}
|
||||
|
||||
pub fn can_cast_to(&self, to: &Type<'a>) -> bool {
|
||||
matches!(self, Type::Integer(_)) && matches!(to, Type::Integer(_))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> fmt::Display for Type<'a> {
|
||||
|
@ -15,16 +15,12 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use leo_asg::*;
|
||||
use leo_ast::Ast;
|
||||
use leo_grammar::Grammar;
|
||||
|
||||
use std::path::Path;
|
||||
use leo_parser::parse_ast;
|
||||
|
||||
mod fail;
|
||||
mod pass;
|
||||
|
||||
const TESTING_FILEPATH: &str = "input.leo";
|
||||
const TESTING_PROGRAM_NAME: &str = "test_program";
|
||||
|
||||
fn load_asg(program_string: &str) -> Result<Program<'static>, AsgConvertError> {
|
||||
load_asg_imports(make_test_context(), program_string, &mut NullImportResolver)
|
||||
@ -35,8 +31,7 @@ fn load_asg_imports<'a, T: ImportResolver<'a>>(
|
||||
program_string: &str,
|
||||
imports: &mut T,
|
||||
) -> Result<Program<'a>, AsgConvertError> {
|
||||
let grammar = Grammar::new(Path::new(&TESTING_FILEPATH), program_string)?;
|
||||
let ast = Ast::new(TESTING_PROGRAM_NAME, &grammar)?;
|
||||
let ast = parse_ast(&TESTING_FILEPATH, program_string)?;
|
||||
InternalProgram::new(context, &ast.as_repr(), imports)
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@ function main(s: bool, c: address) {
|
||||
let a = address(aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8);
|
||||
let b = address(aleo18qgam03qe483tdrcc3fkqwpp38ehff4a2xma6lu7hams6lfpgcpq3dq05r);
|
||||
|
||||
let r = if s? a: b;
|
||||
let r = s? a: b;
|
||||
|
||||
console.assert(r == c);
|
||||
}
|
6
asg/tests/pass/array/implicit.leo
Normal file
6
asg/tests/pass/array/implicit.leo
Normal file
@ -0,0 +1,6 @@
|
||||
function main(){
|
||||
let a = [1u8, 2u8, 3u8, 4];
|
||||
let b = [1u8, 2u8, 3, 4u8];
|
||||
let c = [1u8, 2, 3u8, 4u8];
|
||||
let d = [1, 2u8, 3u8, 4u8];
|
||||
}
|
@ -104,6 +104,12 @@ fn test_slice_lower() {
|
||||
load_asg(program_string).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_implicit() {
|
||||
let program_string = include_str!("implicit.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");
|
||||
|
@ -8,7 +8,7 @@ circuit PedersenHash {
|
||||
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;
|
||||
let base = bits[i] ? self.parameters[i] : 0u32;
|
||||
digest += base;
|
||||
}
|
||||
return digest
|
||||
|
@ -1,5 +1,5 @@
|
||||
function main(s: bool, a: field, b: field, c: field) {
|
||||
let r = if s ? a : b;
|
||||
let r = s ? a : b;
|
||||
|
||||
console.assert(r == c);
|
||||
}
|
@ -15,10 +15,7 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{load_asg, make_test_context};
|
||||
use leo_ast::Ast;
|
||||
use leo_grammar::Grammar;
|
||||
|
||||
use std::path::Path;
|
||||
use leo_parser::parse_ast;
|
||||
|
||||
#[test]
|
||||
fn test_basic() {
|
||||
@ -56,6 +53,7 @@ fn test_function_rename() {
|
||||
|
||||
#[test]
|
||||
fn test_imports() {
|
||||
let import_name = "test-import".to_string();
|
||||
let context = make_test_context();
|
||||
let mut imports = crate::mocked_resolver(&context);
|
||||
let test_import = r#"
|
||||
@ -70,7 +68,7 @@ fn test_imports() {
|
||||
"#;
|
||||
imports
|
||||
.packages
|
||||
.insert("test-import".to_string(), load_asg(test_import).unwrap());
|
||||
.insert(import_name.clone(), load_asg(test_import).unwrap());
|
||||
let program_string = r#"
|
||||
import test-import.foo;
|
||||
|
||||
@ -79,17 +77,11 @@ fn test_imports() {
|
||||
}
|
||||
"#;
|
||||
|
||||
let test_import_grammar = Grammar::new(Path::new("test-import.leo"), test_import).unwrap();
|
||||
println!(
|
||||
"{}",
|
||||
serde_json::to_string(Ast::new("test-import", &test_import_grammar).unwrap().as_repr()).unwrap()
|
||||
);
|
||||
let test_import_ast = parse_ast(&import_name, test_import).unwrap();
|
||||
println!("{}", serde_json::to_string(test_import_ast.as_repr()).unwrap());
|
||||
|
||||
let test_grammar = Grammar::new(Path::new("test.leo"), program_string).unwrap();
|
||||
println!(
|
||||
"{}",
|
||||
serde_json::to_string(Ast::new("test", &test_grammar).unwrap().as_repr()).unwrap()
|
||||
);
|
||||
let test_ast = parse_ast("test.leo", program_string).unwrap();
|
||||
println!("{}", serde_json::to_string(test_ast.as_repr()).unwrap());
|
||||
|
||||
let asg = crate::load_asg_imports(&context, program_string, &mut imports).unwrap();
|
||||
let reformed_ast = leo_asg::reform_ast(&asg);
|
||||
|
@ -1,5 +1,5 @@
|
||||
function main(s: bool, a: group, b: group, c: group) {
|
||||
let r = if s ? a : b;
|
||||
let r = s ? a : b;
|
||||
|
||||
console.assert(r == c);
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
function main(s: bool, a: i128, b: i128, c: i128) {
|
||||
let r = if s ? a : b;
|
||||
let r = s ? a : b;
|
||||
|
||||
console.assert(r == c);
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
function main(s: bool, a: i16, b: i16, c: i16) {
|
||||
let r = if s ? a : b;
|
||||
let r = s ? a : b;
|
||||
|
||||
console.assert(r == c);
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
function main(s: bool, a: i32, b: i32, c: i32) {
|
||||
let r = if s ? a : b;
|
||||
let r = s ? a : b;
|
||||
|
||||
console.assert(r == c);
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
function main(s: bool, a: i64, b: i64, c: i64) {
|
||||
let r = if s ? a : b;
|
||||
let r = s ? a : b;
|
||||
|
||||
console.assert(r == c);
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
function main(s: bool, a: i8, b: i8, c: i8) {
|
||||
let r = if s ? a : b;
|
||||
let r = s ? a : b;
|
||||
|
||||
console.assert(r == c);
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
function main(s: bool, a: u128, b: u128, c: u128) {
|
||||
let r = if s ? a : b;
|
||||
let r = s ? a : b;
|
||||
|
||||
console.assert(r == c);
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
function main(s: bool, a: u16, b: u16, c: u16) {
|
||||
let r = if s ? a : b;
|
||||
let r = s ? a : b;
|
||||
|
||||
console.assert(r == c);
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
function main(s: bool, a: u32, b: u32, c: u32) {
|
||||
let r = if s ? a : b;
|
||||
let r = s ? a : b;
|
||||
|
||||
console.assert(r == c);
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
function main(s: bool, a: u64, b: u64, c: u64) {
|
||||
let r = if s ? a : b;
|
||||
let r = s ? a : b;
|
||||
|
||||
console.assert(r == c);
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
function main(s: bool, a: u8, b: u8, c: u8) {
|
||||
let r = if s ? a : b;
|
||||
let r = s ? a : b;
|
||||
|
||||
console.assert(r == c);
|
||||
}
|
@ -7,7 +7,7 @@ function main(a: bool) {
|
||||
}
|
||||
}
|
||||
|
||||
let r: u32 = if a ? 6 : 0;
|
||||
let r: u32 = a ? 6 : 0;
|
||||
|
||||
console.assert(r == b);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
function main(a: bool, b: bool) {
|
||||
let c = if a ? true : false;
|
||||
let c = a ? true : false;
|
||||
|
||||
let d = c == b;
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "leo-ast"
|
||||
version = "1.2.2"
|
||||
version = "1.2.3"
|
||||
authors = [ "The Aleo Team <hello@aleo.org>" ]
|
||||
description = "Core AST of the Leo programming language"
|
||||
homepage = "https://aleo.org"
|
||||
@ -17,22 +17,9 @@ include = [ "Cargo.toml", "src", "README.md", "LICENSE.md" ]
|
||||
license = "GPL-3.0"
|
||||
edition = "2018"
|
||||
|
||||
[[bin]]
|
||||
name = "leo_ast"
|
||||
path = "src/main.rs"
|
||||
|
||||
[[bench]]
|
||||
name = "leo_ast"
|
||||
path = "benches/leo_ast.rs"
|
||||
harness = false
|
||||
|
||||
[dependencies.leo-grammar]
|
||||
path = "../grammar"
|
||||
version = "1.2.2"
|
||||
|
||||
[dependencies.leo-input]
|
||||
path = "../input"
|
||||
version = "1.2.2"
|
||||
version = "1.2.3"
|
||||
|
||||
[dependencies.indexmap]
|
||||
version = "1.6.1"
|
||||
@ -43,6 +30,7 @@ version = "2.0"
|
||||
|
||||
[dependencies.serde]
|
||||
version = "1.0"
|
||||
features = ["derive", "rc"]
|
||||
|
||||
[dependencies.serde_json]
|
||||
version = "1.0"
|
||||
@ -55,4 +43,4 @@ version = "0.3"
|
||||
|
||||
[features]
|
||||
default = [ ]
|
||||
ci_skip = [ "leo-grammar/ci_skip" ]
|
||||
ci_skip = [ ]
|
||||
|
@ -14,84 +14,13 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{Circuit, DeprecatedError, Function, FunctionInput, Identifier, ImportStatement, TestFunction};
|
||||
use leo_grammar::{
|
||||
annotations::{Annotation, AnnotationArguments, AnnotationName},
|
||||
definitions::{AnnotatedDefinition, Definition},
|
||||
};
|
||||
use crate::{Identifier, Span};
|
||||
|
||||
use std::convert::TryFrom;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use indexmap::IndexMap;
|
||||
|
||||
pub fn load_annotation(
|
||||
annotated_definition: AnnotatedDefinition,
|
||||
_imports: &mut Vec<ImportStatement>,
|
||||
_circuits: &mut IndexMap<Identifier, Circuit>,
|
||||
_functions: &mut IndexMap<Identifier, Function>,
|
||||
tests: &mut IndexMap<Identifier, TestFunction>,
|
||||
_expected: &mut Vec<FunctionInput>,
|
||||
) -> Result<(), DeprecatedError> {
|
||||
let ast_annotation = annotated_definition.annotation;
|
||||
let ast_definition = *annotated_definition.definition;
|
||||
|
||||
match ast_definition {
|
||||
Definition::Import(_) => {
|
||||
unimplemented!("annotated imports are not supported yet");
|
||||
}
|
||||
Definition::Circuit(_) => {
|
||||
unimplemented!("annotated circuits are not supported yet");
|
||||
}
|
||||
Definition::Function(function) => match ast_annotation.name {
|
||||
// If it's deprecated for more than one type of syntax,
|
||||
// we could just call it before the match on ast_definition.
|
||||
AnnotationName::Context(_) => Err(DeprecatedError::try_from(ast_annotation.name).unwrap()),
|
||||
AnnotationName::Test(_) => {
|
||||
let ident = Identifier::from(function.identifier.clone());
|
||||
_functions.remove(&ident);
|
||||
|
||||
let test_function = leo_grammar::functions::TestFunction::from(function);
|
||||
let test = TestFunction::from(test_function);
|
||||
tests.insert(ident, test.clone());
|
||||
|
||||
load_annotated_test(test, ast_annotation, tests);
|
||||
Ok(())
|
||||
}
|
||||
},
|
||||
Definition::Deprecated(_) => Ok(()),
|
||||
Definition::Annotated(_) => {
|
||||
unimplemented!("nested annotations are not supported yet");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load_annotated_test(test: TestFunction, annotation: Annotation, tests: &mut IndexMap<Identifier, TestFunction>) {
|
||||
let name = annotation.name;
|
||||
let ast_arguments = annotation.arguments;
|
||||
|
||||
match name {
|
||||
AnnotationName::Test(_) if ast_arguments.is_some() => {
|
||||
load_annotated_test_context(test, ast_arguments.unwrap(), tests)
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load_annotated_test_context(
|
||||
mut test: TestFunction,
|
||||
ast_arguments: AnnotationArguments,
|
||||
tests: &mut IndexMap<Identifier, TestFunction>,
|
||||
) {
|
||||
let arguments = ast_arguments.arguments;
|
||||
|
||||
if arguments.len() != 1 {
|
||||
panic!("text context annotation must have one argument identifier")
|
||||
}
|
||||
|
||||
let ast_input_file = arguments[0].to_owned();
|
||||
let input_file = Identifier::from(ast_input_file);
|
||||
|
||||
test.input_file = Some(input_file);
|
||||
|
||||
tests.insert(test.function.identifier.clone(), test);
|
||||
#[derive(Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct Annotation {
|
||||
pub span: Span,
|
||||
pub name: Identifier,
|
||||
pub arguments: Vec<String>,
|
||||
}
|
||||
|
@ -15,7 +15,6 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{CircuitMember, Identifier};
|
||||
use leo_grammar::circuits::Circuit as GrammarCircuit;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
@ -26,15 +25,6 @@ pub struct Circuit {
|
||||
pub members: Vec<CircuitMember>,
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarCircuit<'ast>> for Circuit {
|
||||
fn from(circuit: GrammarCircuit<'ast>) -> Self {
|
||||
let circuit_name = Identifier::from(circuit.identifier);
|
||||
let members = circuit.members.into_iter().map(CircuitMember::from).collect();
|
||||
|
||||
Self { circuit_name, members }
|
||||
}
|
||||
}
|
||||
|
||||
impl Circuit {
|
||||
fn format(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
writeln!(f, "circuit {} {{ ", self.circuit_name)?;
|
||||
|
@ -15,27 +15,11 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{Expression, Identifier};
|
||||
use leo_grammar::circuits::CircuitImpliedVariable;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct CircuitImpliedVariableDefinition {
|
||||
pub identifier: Identifier,
|
||||
pub expression: Expression,
|
||||
}
|
||||
|
||||
impl<'ast> From<CircuitImpliedVariable<'ast>> for CircuitImpliedVariableDefinition {
|
||||
fn from(member: CircuitImpliedVariable<'ast>) -> Self {
|
||||
match member {
|
||||
CircuitImpliedVariable::CircuitVariable(circuit_variable) => Self {
|
||||
identifier: Identifier::from(circuit_variable.identifier),
|
||||
expression: Expression::from(circuit_variable.expression),
|
||||
},
|
||||
CircuitImpliedVariable::Identifier(identifier) => Self {
|
||||
identifier: Identifier::from(identifier.clone()),
|
||||
expression: Expression::from(identifier),
|
||||
},
|
||||
}
|
||||
}
|
||||
pub expression: Option<Expression>,
|
||||
}
|
||||
|
@ -15,10 +15,6 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{Function, Identifier, Type};
|
||||
use leo_grammar::{
|
||||
circuits::{CircuitMember as GrammarCircuitMember, CircuitVariableDefinition as GrammarCircuitVariableDefinition},
|
||||
functions::Function as GrammarFunction,
|
||||
};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
@ -31,30 +27,6 @@ pub enum CircuitMember {
|
||||
CircuitFunction(Function),
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarCircuitVariableDefinition<'ast>> for CircuitMember {
|
||||
fn from(circuit_value: GrammarCircuitVariableDefinition<'ast>) -> Self {
|
||||
CircuitMember::CircuitVariable(
|
||||
Identifier::from(circuit_value.identifier),
|
||||
Type::from(circuit_value.type_),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarFunction<'ast>> for CircuitMember {
|
||||
fn from(circuit_function: GrammarFunction<'ast>) -> Self {
|
||||
CircuitMember::CircuitFunction(Function::from(circuit_function))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarCircuitMember<'ast>> for CircuitMember {
|
||||
fn from(object: GrammarCircuitMember<'ast>) -> Self {
|
||||
match object {
|
||||
GrammarCircuitMember::CircuitVariableDefinition(circuit_value) => CircuitMember::from(circuit_value),
|
||||
GrammarCircuitMember::CircuitFunction(circuit_function) => CircuitMember::from(circuit_function),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for CircuitMember {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
|
@ -15,7 +15,6 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{Expression, Identifier};
|
||||
use leo_grammar::circuits::CircuitVariable;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
@ -24,12 +23,3 @@ pub struct CircuitVariableDefinition {
|
||||
pub identifier: Identifier,
|
||||
pub expression: Expression,
|
||||
}
|
||||
|
||||
impl<'ast> From<CircuitVariable<'ast>> for CircuitVariableDefinition {
|
||||
fn from(member: CircuitVariable<'ast>) -> Self {
|
||||
CircuitVariableDefinition {
|
||||
identifier: Identifier::from(member.identifier),
|
||||
expression: Expression::from(member.expression),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,6 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::PositiveNumber;
|
||||
use leo_grammar::types::ArrayDimensions as GrammarArrayDimensions;
|
||||
use leo_input::types::ArrayDimensions as InputArrayDimensions;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -104,18 +103,6 @@ impl ArrayDimensions {
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new [`ArrayDimensions`] from a [`GrammarArrayDimensions`] in a Leo program file.
|
||||
impl<'ast> From<GrammarArrayDimensions<'ast>> for ArrayDimensions {
|
||||
fn from(dimensions: GrammarArrayDimensions<'ast>) -> Self {
|
||||
Self(match dimensions {
|
||||
GrammarArrayDimensions::Single(single) => vec![PositiveNumber::from(single.number)],
|
||||
GrammarArrayDimensions::Multiple(multiple) => {
|
||||
multiple.numbers.into_iter().map(PositiveNumber::from).collect()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new [`ArrayDimensions`] from a [`InputArrayDimensions`] in a Leo program file.
|
||||
impl<'ast> From<InputArrayDimensions<'ast>> for ArrayDimensions {
|
||||
fn from(dimensions: InputArrayDimensions<'ast>) -> Self {
|
||||
|
@ -14,26 +14,15 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{InputKeyword, MutSelfKeyword, SelfKeyword, Span};
|
||||
use leo_grammar::{
|
||||
annotations::AnnotationArgument,
|
||||
common::{
|
||||
Identifier as GrammarIdentifier,
|
||||
KeywordOrIdentifier,
|
||||
MutSelfKeyword as GrammarMutSelfKeyword,
|
||||
SelfKeyword as GrammarSelfKeyword,
|
||||
SelfKeywordOrIdentifier,
|
||||
},
|
||||
expressions::CircuitName,
|
||||
functions::InputKeyword as GrammarInputKeyword,
|
||||
imports::PackageName as GrammarPackageName,
|
||||
types::SelfType,
|
||||
};
|
||||
use crate::Span;
|
||||
use leo_input::common::Identifier as InputIdentifier;
|
||||
|
||||
use crate::Node;
|
||||
use serde::{
|
||||
de::{self, Visitor},
|
||||
de::{
|
||||
Visitor,
|
||||
{self},
|
||||
},
|
||||
Deserialize,
|
||||
Deserializer,
|
||||
Serialize,
|
||||
@ -74,10 +63,10 @@ impl Identifier {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_with_span(name: &str, span: &Span) -> Self {
|
||||
pub fn new_with_span(name: &str, span: Span) -> Self {
|
||||
Self {
|
||||
name: name.to_owned(),
|
||||
span: span.to_owned(),
|
||||
span,
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,24 +79,6 @@ impl Identifier {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarIdentifier<'ast>> for Identifier {
|
||||
fn from(identifier: GrammarIdentifier<'ast>) -> Self {
|
||||
Self {
|
||||
name: identifier.value,
|
||||
span: Span::from(identifier.span),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarPackageName<'ast>> for Identifier {
|
||||
fn from(name: GrammarPackageName<'ast>) -> Self {
|
||||
Self {
|
||||
name: name.value,
|
||||
span: Span::from(name.span),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<InputIdentifier<'ast>> for Identifier {
|
||||
fn from(identifier: InputIdentifier<'ast>) -> Self {
|
||||
Self {
|
||||
@ -117,106 +88,6 @@ impl<'ast> From<InputIdentifier<'ast>> for Identifier {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<AnnotationArgument<'ast>> for Identifier {
|
||||
fn from(argument: AnnotationArgument<'ast>) -> Self {
|
||||
Self {
|
||||
name: argument.value,
|
||||
span: Span::from(argument.span),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<KeywordOrIdentifier<'ast>> for Identifier {
|
||||
fn from(name: KeywordOrIdentifier<'ast>) -> Self {
|
||||
match name {
|
||||
KeywordOrIdentifier::Identifier(keyword) => Identifier::from(keyword),
|
||||
KeywordOrIdentifier::SelfType(self_type) => Identifier::from(self_type),
|
||||
KeywordOrIdentifier::Input(keyword) => Identifier::from(keyword),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<SelfKeywordOrIdentifier<'ast>> for Identifier {
|
||||
fn from(name: SelfKeywordOrIdentifier<'ast>) -> Self {
|
||||
match name {
|
||||
SelfKeywordOrIdentifier::Identifier(identifier) => Identifier::from(identifier),
|
||||
SelfKeywordOrIdentifier::SelfKeyword(keyword) => Identifier::from(keyword),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarSelfKeyword<'ast>> for Identifier {
|
||||
fn from(grammar: GrammarSelfKeyword<'ast>) -> Self {
|
||||
Self {
|
||||
name: grammar.keyword,
|
||||
span: Span::from(grammar.span),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SelfKeyword> for Identifier {
|
||||
fn from(keyword: SelfKeyword) -> Self {
|
||||
Self {
|
||||
name: keyword.to_string(),
|
||||
span: keyword.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarMutSelfKeyword<'ast>> for Identifier {
|
||||
fn from(grammar: GrammarMutSelfKeyword<'ast>) -> Self {
|
||||
Self {
|
||||
name: grammar.to_string(),
|
||||
span: Span::from(grammar.span),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<MutSelfKeyword> for Identifier {
|
||||
fn from(keyword: MutSelfKeyword) -> Self {
|
||||
Self {
|
||||
name: keyword.to_string(),
|
||||
span: keyword.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarInputKeyword<'ast>> for Identifier {
|
||||
fn from(grammar: GrammarInputKeyword<'ast>) -> Self {
|
||||
Self {
|
||||
name: grammar.keyword,
|
||||
span: Span::from(grammar.span),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<InputKeyword> for Identifier {
|
||||
fn from(keyword: InputKeyword) -> Self {
|
||||
Self {
|
||||
name: keyword.to_string(),
|
||||
span: keyword.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<CircuitName<'ast>> for Identifier {
|
||||
fn from(name: CircuitName<'ast>) -> Self {
|
||||
match name {
|
||||
CircuitName::SelfType(self_type) => Identifier::from(self_type),
|
||||
CircuitName::Identifier(identifier) => Identifier::from(identifier),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<SelfType<'ast>> for Identifier {
|
||||
fn from(self_type: SelfType<'ast>) -> Self {
|
||||
Self {
|
||||
name: self_type.keyword,
|
||||
span: Span::from(self_type.span),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Identifier {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", self.name)
|
||||
|
@ -15,7 +15,6 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{Node, Span};
|
||||
use leo_grammar::functions::InputKeyword as GrammarInputKeyword;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
@ -27,14 +26,6 @@ pub struct InputKeyword {
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarInputKeyword<'ast>> for InputKeyword {
|
||||
fn from(grammar: GrammarInputKeyword<'ast>) -> Self {
|
||||
Self {
|
||||
span: Span::from(grammar.span),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for InputKeyword {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "input")
|
||||
|
@ -15,7 +15,6 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{Node, Span};
|
||||
use leo_grammar::common::MutSelfKeyword as GrammarMutSelfKeyword;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
@ -26,14 +25,6 @@ pub struct MutSelfKeyword {
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarMutSelfKeyword<'ast>> for MutSelfKeyword {
|
||||
fn from(grammar: GrammarMutSelfKeyword<'ast>) -> Self {
|
||||
Self {
|
||||
span: Span::from(grammar.span),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for MutSelfKeyword {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "mut self")
|
||||
|
@ -14,7 +14,6 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use leo_grammar::values::PositiveNumber as GrammarPositiveNumber;
|
||||
use leo_input::values::PositiveNumber as InputPositiveNumber;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -35,13 +34,6 @@ impl PositiveNumber {
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new [`PositiveNumber`] from a [`GrammarPositiveNumber`] in a Leo program file.
|
||||
impl<'ast> From<GrammarPositiveNumber<'ast>> for PositiveNumber {
|
||||
fn from(array: GrammarPositiveNumber<'ast>) -> Self {
|
||||
Self { value: array.value }
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new [`PositiveNumber`] from an [`InputPositiveNumber`] in a Leo input file.
|
||||
impl<'ast> From<InputPositiveNumber<'ast>> for PositiveNumber {
|
||||
fn from(array: InputPositiveNumber<'ast>) -> Self {
|
||||
|
@ -15,7 +15,6 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{Node, Span};
|
||||
use leo_grammar::common::SelfKeyword as GrammarSelfKeyword;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
@ -27,14 +26,6 @@ pub struct SelfKeyword {
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarSelfKeyword<'ast>> for SelfKeyword {
|
||||
fn from(grammar: GrammarSelfKeyword<'ast>) -> Self {
|
||||
Self {
|
||||
span: Span::from(grammar.span),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for SelfKeyword {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "self")
|
||||
|
@ -14,62 +14,85 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use pest::Span as GrammarSpan;
|
||||
use std::{fmt, rc::Rc};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
||||
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, Hash)]
|
||||
pub struct Span {
|
||||
/// text of input string
|
||||
pub text: String,
|
||||
/// program line
|
||||
pub line: usize,
|
||||
/// start column
|
||||
pub start: usize,
|
||||
/// end column
|
||||
pub end: usize,
|
||||
pub line_start: usize,
|
||||
pub line_stop: usize,
|
||||
pub col_start: usize,
|
||||
pub col_stop: usize,
|
||||
pub path: Rc<String>,
|
||||
}
|
||||
|
||||
impl PartialEq for Span {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.line == other.line && self.start == other.start && self.end == other.end
|
||||
impl fmt::Display for Span {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
if self.line_start == self.line_stop {
|
||||
write!(f, "{}:{}-{}", self.line_start, self.col_start, self.col_stop)
|
||||
} else {
|
||||
write!(
|
||||
f,
|
||||
"{}:{}-{}:{}",
|
||||
self.line_start, self.col_start, self.line_stop, self.col_stop
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for Span {}
|
||||
impl<'ast> From<pest::Span<'ast>> for Span {
|
||||
fn from(span: pest::Span) -> Self {
|
||||
let start = span.start_pos().line_col();
|
||||
let end = span.end_pos().line_col();
|
||||
|
||||
impl Hash for Span {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.line.hash(state);
|
||||
self.start.hash(state);
|
||||
self.end.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl Span {
|
||||
pub fn from_internal_string(value: &str) -> Span {
|
||||
Span {
|
||||
text: value.to_string(),
|
||||
line: 0,
|
||||
start: 0,
|
||||
end: 0,
|
||||
line_start: start.0,
|
||||
line_stop: end.0,
|
||||
col_start: start.1,
|
||||
col_stop: end.1,
|
||||
path: Rc::new(String::new()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarSpan<'ast>> for Span {
|
||||
fn from(span: GrammarSpan<'ast>) -> Self {
|
||||
let mut text = " ".to_string();
|
||||
let line_col = span.start_pos().line_col();
|
||||
let end = span.end_pos().line_col().1;
|
||||
impl std::ops::Add for &Span {
|
||||
type Output = Span;
|
||||
|
||||
text.push_str(span.start_pos().line_of().trim_end());
|
||||
fn add(self, other: &Span) -> Span {
|
||||
self.clone() + other.clone()
|
||||
}
|
||||
}
|
||||
|
||||
Self {
|
||||
text,
|
||||
line: line_col.0,
|
||||
start: line_col.1,
|
||||
end,
|
||||
impl std::ops::Add for Span {
|
||||
type Output = Self;
|
||||
|
||||
#[allow(clippy::comparison_chain)]
|
||||
fn add(self, other: Self) -> Self {
|
||||
if self.line_start == other.line_stop {
|
||||
Span {
|
||||
line_start: self.line_start,
|
||||
line_stop: self.line_stop,
|
||||
col_start: self.col_start.min(other.col_start),
|
||||
col_stop: self.col_stop.max(other.col_stop),
|
||||
path: self.path,
|
||||
}
|
||||
} else if self.line_start < other.line_stop {
|
||||
Span {
|
||||
line_start: self.line_start,
|
||||
line_stop: other.line_stop,
|
||||
col_start: self.col_start,
|
||||
col_stop: other.col_stop,
|
||||
path: self.path,
|
||||
}
|
||||
} else {
|
||||
Span {
|
||||
line_start: other.line_start,
|
||||
line_stop: self.line_stop,
|
||||
col_start: other.col_start,
|
||||
col_stop: self.col_stop,
|
||||
path: self.path,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,10 +15,6 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{Expression, Node, Span};
|
||||
use leo_grammar::{
|
||||
common::SpreadOrExpression as GrammarSpreadOrExpression,
|
||||
expressions::Expression as GrammarExpression,
|
||||
};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
@ -30,25 +26,6 @@ pub enum SpreadOrExpression {
|
||||
Expression(Expression),
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarSpreadOrExpression<'ast>> for SpreadOrExpression {
|
||||
fn from(s_or_e: GrammarSpreadOrExpression<'ast>) -> Self {
|
||||
match s_or_e {
|
||||
GrammarSpreadOrExpression::Spread(spread) => {
|
||||
SpreadOrExpression::Spread(Expression::from(spread.expression))
|
||||
}
|
||||
GrammarSpreadOrExpression::Expression(expression) => {
|
||||
SpreadOrExpression::Expression(Expression::from(expression))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarExpression<'ast>> for SpreadOrExpression {
|
||||
fn from(expression: GrammarExpression<'ast>) -> Self {
|
||||
SpreadOrExpression::Expression(Expression::from(expression))
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for SpreadOrExpression {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
|
@ -14,9 +14,9 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::Span;
|
||||
use crate::{LeoError, Span};
|
||||
|
||||
use std::{fmt, path::Path};
|
||||
use std::fmt;
|
||||
|
||||
pub const INDENT: &str = " ";
|
||||
|
||||
@ -28,68 +28,59 @@ pub const INDENT: &str = " ";
|
||||
/// |
|
||||
/// = undefined value `x`
|
||||
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
|
||||
pub struct Error {
|
||||
pub struct FormattedError {
|
||||
/// File path where error occurred
|
||||
pub path: Option<String>,
|
||||
/// Line number
|
||||
pub line: usize,
|
||||
/// Line start number
|
||||
pub line_start: usize,
|
||||
/// Line end number
|
||||
pub line_stop: usize,
|
||||
/// Starting column
|
||||
pub start: usize,
|
||||
/// Ending column
|
||||
pub end: usize,
|
||||
/// Text of errored line
|
||||
pub text: String,
|
||||
/// Text of errored lines
|
||||
pub text: Option<Vec<String>>,
|
||||
/// Error explanation
|
||||
pub message: String,
|
||||
}
|
||||
|
||||
impl Error {
|
||||
pub fn new_from_span(message: String, span: Span) -> Self {
|
||||
impl FormattedError {
|
||||
pub fn new_from_span(message: String, span: &Span) -> Self {
|
||||
Self {
|
||||
path: None,
|
||||
line: span.line,
|
||||
start: span.start,
|
||||
end: span.end,
|
||||
text: span.text,
|
||||
line_start: span.line_start,
|
||||
line_stop: span.line_stop,
|
||||
start: span.col_start,
|
||||
end: span.col_stop,
|
||||
text: None,
|
||||
message,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_from_span_with_path(message: String, span: Span, path: &Path) -> Self {
|
||||
Self {
|
||||
path: Some(format!("{:?}", path)),
|
||||
line: span.line,
|
||||
start: span.start,
|
||||
end: span.end,
|
||||
text: span.text,
|
||||
message,
|
||||
impl LeoError for FormattedError {
|
||||
fn set_path(&mut self, path: &str, content: &[String]) {
|
||||
self.path = Some(path.to_string());
|
||||
if self.line_stop - 1 > content.len() {
|
||||
self.text = Some(vec!["corrupt file".to_string()]);
|
||||
return;
|
||||
}
|
||||
assert!(self.line_stop >= self.line_start);
|
||||
// if self.line_stop == self.line_start {
|
||||
// self.text = Some(vec![content[self.line_start - 1][self.start - 1..self.end - 1].to_string()]);
|
||||
// } else {
|
||||
self.text = Some(
|
||||
content[self.line_start - 1..self.line_stop]
|
||||
.iter()
|
||||
.map(|x| x.to_string())
|
||||
.collect(),
|
||||
);
|
||||
// }
|
||||
}
|
||||
|
||||
pub fn set_path(&mut self, path: &Path) {
|
||||
self.path = Some(format!("{:?}", path));
|
||||
}
|
||||
|
||||
pub fn format(&self) -> String {
|
||||
let path = self.path.as_ref().map(|path| format!("{}:", path)).unwrap_or_default();
|
||||
let underline = underline(self.start, self.end);
|
||||
|
||||
format!(
|
||||
"{indent }--> {path} {line}:{start}\n\
|
||||
{indent } |\n\
|
||||
{line:width$} | {text}\n\
|
||||
{indent } | {underline}\n\
|
||||
{indent } |\n\
|
||||
{indent } = {message}",
|
||||
indent = INDENT,
|
||||
width = INDENT.len(),
|
||||
path = path,
|
||||
line = self.line,
|
||||
start = self.start,
|
||||
text = self.text,
|
||||
underline = underline,
|
||||
message = self.message,
|
||||
)
|
||||
fn get_path(&self) -> Option<&str> {
|
||||
self.path.as_deref()
|
||||
}
|
||||
}
|
||||
|
||||
@ -112,13 +103,46 @@ fn underline(mut start: usize, mut end: usize) -> String {
|
||||
underline
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
impl fmt::Display for FormattedError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", self.format())
|
||||
let path = self.path.as_ref().map(|path| format!("{}:", path)).unwrap_or_default();
|
||||
let underline = underline(self.start - 1, self.end - 1);
|
||||
|
||||
write!(
|
||||
f,
|
||||
"{indent }--> {path} {line_start}:{start}\n\
|
||||
{indent } |\n",
|
||||
indent = INDENT,
|
||||
path = path,
|
||||
line_start = self.line_start,
|
||||
start = self.start,
|
||||
)?;
|
||||
|
||||
if let Some(lines) = &self.text {
|
||||
for (line_no, line) in lines.iter().enumerate() {
|
||||
writeln!(
|
||||
f,
|
||||
"{line_no:width$} | {text}",
|
||||
width = INDENT.len(),
|
||||
line_no = self.line_start + line_no,
|
||||
text = line,
|
||||
)?;
|
||||
}
|
||||
}
|
||||
|
||||
write!(
|
||||
f,
|
||||
"{indent } | {underline}\n\
|
||||
{indent } |\n\
|
||||
{indent } = {message}",
|
||||
indent = INDENT,
|
||||
underline = underline,
|
||||
message = self.message,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for Error {
|
||||
impl std::error::Error for FormattedError {
|
||||
fn description(&self) -> &str {
|
||||
&self.message
|
||||
}
|
||||
@ -126,12 +150,13 @@ impl std::error::Error for Error {
|
||||
|
||||
#[test]
|
||||
fn test_error() {
|
||||
let err = Error {
|
||||
let err = FormattedError {
|
||||
path: Some("file.leo".to_string()),
|
||||
line: 2,
|
||||
line_start: 2,
|
||||
line_stop: 2,
|
||||
start: 8,
|
||||
end: 9,
|
||||
text: "let a = x;".to_string(),
|
||||
text: Some(vec!["let a = x;".to_string()]),
|
||||
message: "undefined value `x`".to_string(),
|
||||
};
|
||||
|
||||
|
@ -14,30 +14,11 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
pub mod deprecated;
|
||||
pub use deprecated::*;
|
||||
|
||||
pub mod error;
|
||||
pub use error::*;
|
||||
|
||||
use error::Error as FormattedError;
|
||||
pub trait LeoError {
|
||||
fn get_path(&self) -> Option<&str>;
|
||||
|
||||
use leo_grammar::ParserError;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum AstError {
|
||||
#[error("{}", _0)]
|
||||
DeprecatedError(#[from] DeprecatedError),
|
||||
|
||||
#[error("{}", _0)]
|
||||
Error(#[from] FormattedError),
|
||||
|
||||
#[error("{}", _0)]
|
||||
IoError(#[from] std::io::Error),
|
||||
|
||||
#[error("{}", _0)]
|
||||
ParserError(#[from] ParserError),
|
||||
|
||||
#[error("{}", _0)]
|
||||
JsonError(#[from] serde_json::error::Error),
|
||||
fn set_path(&mut self, path: &str, contents: &[String]);
|
||||
}
|
||||
|
@ -31,6 +31,13 @@ pub enum BinaryOperation {
|
||||
Gt,
|
||||
Le,
|
||||
Lt,
|
||||
BitOr,
|
||||
BitAnd,
|
||||
BitXor,
|
||||
Shr,
|
||||
ShrSigned,
|
||||
Shl,
|
||||
Mod,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
@ -55,6 +62,13 @@ impl AsRef<str> for BinaryOperation {
|
||||
BinaryOperation::Gt => ">",
|
||||
BinaryOperation::Le => "<=",
|
||||
BinaryOperation::Lt => "<",
|
||||
BinaryOperation::BitOr => "|",
|
||||
BinaryOperation::BitAnd => "&",
|
||||
BinaryOperation::BitXor => "^",
|
||||
BinaryOperation::Shr => ">>",
|
||||
BinaryOperation::ShrSigned => ">>>",
|
||||
BinaryOperation::Shl => "<<",
|
||||
BinaryOperation::Mod => "%",
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -66,6 +80,13 @@ impl BinaryOperation {
|
||||
| BinaryOperation::Sub
|
||||
| BinaryOperation::Mul
|
||||
| BinaryOperation::Div
|
||||
| BinaryOperation::BitOr
|
||||
| BinaryOperation::BitAnd
|
||||
| BinaryOperation::BitXor
|
||||
| BinaryOperation::Shr
|
||||
| BinaryOperation::ShrSigned
|
||||
| BinaryOperation::Shl
|
||||
| BinaryOperation::Mod
|
||||
| BinaryOperation::Pow => BinaryOperationClass::Numeric,
|
||||
BinaryOperation::Or
|
||||
| BinaryOperation::And
|
||||
|
@ -14,24 +14,29 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{ast::Rule, expressions::Expression, SpanDef};
|
||||
use crate::Type;
|
||||
|
||||
use pest::Span;
|
||||
use pest_ast::FromPest;
|
||||
use serde::Serialize;
|
||||
use std::fmt;
|
||||
use super::*;
|
||||
|
||||
#[derive(Clone, Debug, FromPest, PartialEq, Serialize)]
|
||||
#[pest_ast(rule(Rule::spread))]
|
||||
pub struct Spread<'ast> {
|
||||
pub expression: Expression<'ast>,
|
||||
#[pest_ast(outer())]
|
||||
#[serde(with = "SpanDef")]
|
||||
pub span: Span<'ast>,
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct CastExpression {
|
||||
pub inner: Box<Expression>,
|
||||
pub target_type: Type,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
impl<'ast> fmt::Display for Spread<'ast> {
|
||||
impl fmt::Display for CastExpression {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "...{}", self.expression)
|
||||
write!(f, "{} as {}", self.inner, self.target_type)
|
||||
}
|
||||
}
|
||||
|
||||
impl Node for CastExpression {
|
||||
fn span(&self) -> &Span {
|
||||
&self.span
|
||||
}
|
||||
|
||||
fn set_span(&mut self, span: Span) {
|
||||
self.span = span;
|
||||
}
|
||||
}
|
@ -27,7 +27,11 @@ impl fmt::Display for CircuitInitExpression {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{} {{", self.name)?;
|
||||
for (i, member) in self.members.iter().enumerate() {
|
||||
write!(f, "{}: {}", member.identifier, member.expression)?;
|
||||
if let Some(expression) = &member.expression {
|
||||
write!(f, "{}: {}", member.identifier, expression)?;
|
||||
} else {
|
||||
write!(f, "{}", member.identifier)?;
|
||||
}
|
||||
|
||||
if i < self.members.len() - 1 {
|
||||
write!(f, ", ")?;
|
||||
|
@ -24,33 +24,7 @@ use crate::{
|
||||
Span,
|
||||
SpreadOrExpression,
|
||||
};
|
||||
use leo_grammar::{
|
||||
access::{Access, AssigneeAccess, SelfAccess},
|
||||
common::{Assignee, Identifier as GrammarIdentifier, RangeOrExpression as GrammarRangeOrExpression},
|
||||
expressions::{
|
||||
ArrayInitializerExpression,
|
||||
ArrayInlineExpression as GrammarArrayInlineExpression,
|
||||
BinaryExpression as GrammarBinaryExpression,
|
||||
CircuitInlineExpression,
|
||||
Expression as GrammarExpression,
|
||||
PostfixExpression,
|
||||
SelfPostfixExpression,
|
||||
TernaryExpression as GrammarTernaryExpression,
|
||||
UnaryExpression as GrammarUnaryExpression,
|
||||
},
|
||||
operations::{BinaryOperation as GrammarBinaryOperation, UnaryOperation as GrammarUnaryOperation},
|
||||
values::{
|
||||
AddressValue,
|
||||
BooleanValue,
|
||||
FieldValue,
|
||||
GroupValue as GrammarGroupValue,
|
||||
IntegerValue,
|
||||
NumberValue as GrammarNumber,
|
||||
Value,
|
||||
},
|
||||
};
|
||||
|
||||
use leo_grammar::{access::TupleAccess, expressions::TupleExpression};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
@ -84,6 +58,8 @@ mod value;
|
||||
pub use value::*;
|
||||
mod call;
|
||||
pub use call::*;
|
||||
mod cast;
|
||||
pub use cast::*;
|
||||
|
||||
/// Expression that evaluates to a value
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
@ -93,6 +69,7 @@ pub enum Expression {
|
||||
Binary(BinaryExpression),
|
||||
Unary(UnaryExpression),
|
||||
Ternary(TernaryExpression),
|
||||
Cast(CastExpression),
|
||||
|
||||
ArrayInline(ArrayInlineExpression),
|
||||
ArrayInit(ArrayInitExpression),
|
||||
@ -128,6 +105,7 @@ impl Node for Expression {
|
||||
CircuitMemberAccess(n) => n.span(),
|
||||
CircuitStaticFunctionAccess(n) => n.span(),
|
||||
Call(n) => n.span(),
|
||||
Cast(n) => n.span(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -149,11 +127,12 @@ impl Node for Expression {
|
||||
CircuitMemberAccess(n) => n.set_span(span),
|
||||
CircuitStaticFunctionAccess(n) => n.set_span(span),
|
||||
Call(n) => n.set_span(span),
|
||||
Cast(n) => n.set_span(span),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> fmt::Display for Expression {
|
||||
impl fmt::Display for Expression {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
use Expression::*;
|
||||
match &self {
|
||||
@ -172,404 +151,7 @@ impl<'ast> fmt::Display for Expression {
|
||||
CircuitMemberAccess(n) => n.fmt(f),
|
||||
CircuitStaticFunctionAccess(n) => n.fmt(f),
|
||||
Call(n) => n.fmt(f),
|
||||
Cast(n) => n.fmt(f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<CircuitInlineExpression<'ast>> for Expression {
|
||||
fn from(expression: CircuitInlineExpression<'ast>) -> Self {
|
||||
let circuit_name = Identifier::from(expression.name);
|
||||
let members = expression
|
||||
.members
|
||||
.into_iter()
|
||||
.map(CircuitImpliedVariableDefinition::from)
|
||||
.collect::<Vec<CircuitImpliedVariableDefinition>>();
|
||||
|
||||
Expression::CircuitInit(CircuitInitExpression {
|
||||
name: circuit_name,
|
||||
members,
|
||||
span: Span::from(expression.span),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<PostfixExpression<'ast>> for Expression {
|
||||
fn from(expression: PostfixExpression<'ast>) -> Self {
|
||||
let variable = Expression::Identifier(Identifier::from(expression.name));
|
||||
|
||||
// ast::PostFixExpression contains an array of "accesses": `a(34)[42]` is represented as `[a, [Call(34), Select(42)]]`, but Access call expressions
|
||||
// are recursive, so it is `Select(Call(a, 34), 42)`. We apply this transformation here
|
||||
|
||||
// we start with the id, and we fold the array of accesses by wrapping the current value
|
||||
expression
|
||||
.accesses
|
||||
.into_iter()
|
||||
.fold(variable, |acc, access| match access {
|
||||
// Handle array accesses
|
||||
Access::Array(array) => match array.expression {
|
||||
GrammarRangeOrExpression::Expression(expression) => {
|
||||
Expression::ArrayAccess(ArrayAccessExpression {
|
||||
array: Box::new(acc),
|
||||
index: Box::new(Expression::from(expression)),
|
||||
span: Span::from(array.span),
|
||||
})
|
||||
}
|
||||
GrammarRangeOrExpression::Range(range) => {
|
||||
Expression::ArrayRangeAccess(ArrayRangeAccessExpression {
|
||||
array: Box::new(acc),
|
||||
left: range.from.map(Expression::from).map(Box::new),
|
||||
right: range.to.map(Expression::from).map(Box::new),
|
||||
span: Span::from(array.span),
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
// Handle tuple access
|
||||
Access::Tuple(tuple) => Expression::TupleAccess(TupleAccessExpression {
|
||||
tuple: Box::new(acc),
|
||||
index: PositiveNumber::from(tuple.number),
|
||||
span: Span::from(tuple.span),
|
||||
}),
|
||||
|
||||
// Handle function calls
|
||||
Access::Call(function) => Expression::Call(CallExpression {
|
||||
function: Box::new(acc),
|
||||
arguments: function.expressions.into_iter().map(Expression::from).collect(),
|
||||
span: Span::from(function.span),
|
||||
}),
|
||||
|
||||
// Handle circuit member accesses
|
||||
Access::Object(circuit_object) => Expression::CircuitMemberAccess(CircuitMemberAccessExpression {
|
||||
circuit: Box::new(acc),
|
||||
name: Identifier::from(circuit_object.identifier),
|
||||
span: Span::from(circuit_object.span),
|
||||
}),
|
||||
Access::StaticObject(circuit_object) => {
|
||||
Expression::CircuitStaticFunctionAccess(CircuitStaticFunctionAccessExpression {
|
||||
circuit: Box::new(acc),
|
||||
name: Identifier::from(circuit_object.identifier),
|
||||
span: Span::from(circuit_object.span),
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<SelfPostfixExpression<'ast>> for Expression {
|
||||
fn from(expression: SelfPostfixExpression<'ast>) -> Self {
|
||||
let variable = Expression::Identifier(Identifier::from(expression.name));
|
||||
|
||||
// Handle self expression access.
|
||||
let self_expression = match expression.self_access {
|
||||
// Handle circuit member accesses
|
||||
SelfAccess::Object(circuit_object) => Expression::CircuitMemberAccess(CircuitMemberAccessExpression {
|
||||
circuit: Box::new(variable),
|
||||
name: Identifier::from(circuit_object.identifier),
|
||||
span: Span::from(circuit_object.span),
|
||||
}),
|
||||
|
||||
// Handle static access
|
||||
SelfAccess::StaticObject(circuit_object) => {
|
||||
Expression::CircuitStaticFunctionAccess(CircuitStaticFunctionAccessExpression {
|
||||
circuit: Box::new(variable),
|
||||
name: Identifier::from(circuit_object.identifier),
|
||||
span: Span::from(circuit_object.span),
|
||||
})
|
||||
}
|
||||
};
|
||||
// ast::SelfPostFixExpression contains an array of "accesses": `a(34)[42]` is represented as `[a, [Call(34), Select(42)]]`, but Access call expressions
|
||||
// are recursive, so it is `Select(Call(a, 34), 42)`. We apply this transformation here
|
||||
|
||||
// we start with the id, and we fold the array of accesses by wrapping the current value
|
||||
expression
|
||||
.accesses
|
||||
.into_iter()
|
||||
.fold(self_expression, |acc, access| match access {
|
||||
// Handle array accesses
|
||||
Access::Array(array) => match array.expression {
|
||||
GrammarRangeOrExpression::Expression(expression) => {
|
||||
Expression::ArrayAccess(ArrayAccessExpression {
|
||||
array: Box::new(acc),
|
||||
index: Box::new(Expression::from(expression)),
|
||||
span: Span::from(array.span),
|
||||
})
|
||||
}
|
||||
GrammarRangeOrExpression::Range(range) => {
|
||||
Expression::ArrayRangeAccess(ArrayRangeAccessExpression {
|
||||
array: Box::new(acc),
|
||||
left: range.from.map(Expression::from).map(Box::new),
|
||||
right: range.to.map(Expression::from).map(Box::new),
|
||||
span: Span::from(array.span),
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
// Handle tuple access
|
||||
Access::Tuple(tuple) => Expression::TupleAccess(TupleAccessExpression {
|
||||
tuple: Box::new(acc),
|
||||
index: PositiveNumber::from(tuple.number),
|
||||
span: Span::from(tuple.span),
|
||||
}),
|
||||
|
||||
// Handle function calls
|
||||
Access::Call(function) => Expression::Call(CallExpression {
|
||||
function: Box::new(acc),
|
||||
arguments: function.expressions.into_iter().map(Expression::from).collect(),
|
||||
span: Span::from(function.span),
|
||||
}),
|
||||
|
||||
// Handle circuit member accesses
|
||||
Access::Object(circuit_object) => Expression::CircuitMemberAccess(CircuitMemberAccessExpression {
|
||||
circuit: Box::new(acc),
|
||||
name: Identifier::from(circuit_object.identifier),
|
||||
span: Span::from(circuit_object.span),
|
||||
}),
|
||||
Access::StaticObject(circuit_object) => {
|
||||
Expression::CircuitStaticFunctionAccess(CircuitStaticFunctionAccessExpression {
|
||||
circuit: Box::new(acc),
|
||||
name: Identifier::from(circuit_object.identifier),
|
||||
span: Span::from(circuit_object.span),
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarExpression<'ast>> for Expression {
|
||||
fn from(expression: GrammarExpression<'ast>) -> Self {
|
||||
match expression {
|
||||
GrammarExpression::Value(value) => Expression::from(value),
|
||||
GrammarExpression::Identifier(variable) => Expression::from(variable),
|
||||
GrammarExpression::Unary(expression) => Expression::from(*expression),
|
||||
GrammarExpression::Binary(expression) => Expression::from(*expression),
|
||||
GrammarExpression::Ternary(expression) => Expression::from(*expression),
|
||||
GrammarExpression::ArrayInline(expression) => Expression::from(expression),
|
||||
GrammarExpression::ArrayInitializer(expression) => Expression::from(*expression),
|
||||
GrammarExpression::Tuple(expression) => Expression::from(expression),
|
||||
GrammarExpression::CircuitInline(expression) => Expression::from(expression),
|
||||
GrammarExpression::Postfix(expression) => Expression::from(expression),
|
||||
GrammarExpression::SelfPostfix(expression) => Expression::from(expression),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Assignee -> Expression for operator assign statements
|
||||
impl<'ast> From<Assignee<'ast>> for Expression {
|
||||
fn from(assignee: Assignee<'ast>) -> Self {
|
||||
let variable = Expression::Identifier(Identifier::from(assignee.name));
|
||||
|
||||
// we start with the id, and we fold the array of accesses by wrapping the current value
|
||||
assignee
|
||||
.accesses
|
||||
.into_iter()
|
||||
.fold(variable, |acc, access| match access {
|
||||
AssigneeAccess::Member(circuit_member) => {
|
||||
Expression::CircuitMemberAccess(CircuitMemberAccessExpression {
|
||||
circuit: Box::new(acc),
|
||||
name: Identifier::from(circuit_member.identifier),
|
||||
span: Span::from(circuit_member.span),
|
||||
})
|
||||
}
|
||||
AssigneeAccess::Array(array) => match array.expression {
|
||||
GrammarRangeOrExpression::Expression(expression) => {
|
||||
Expression::ArrayAccess(ArrayAccessExpression {
|
||||
array: Box::new(acc),
|
||||
index: Box::new(Expression::from(expression)),
|
||||
span: Span::from(array.span),
|
||||
})
|
||||
}
|
||||
GrammarRangeOrExpression::Range(range) => {
|
||||
Expression::ArrayRangeAccess(ArrayRangeAccessExpression {
|
||||
array: Box::new(acc),
|
||||
left: range.from.map(Expression::from).map(Box::new),
|
||||
right: range.to.map(Expression::from).map(Box::new),
|
||||
span: Span::from(array.span),
|
||||
})
|
||||
}
|
||||
},
|
||||
AssigneeAccess::Tuple(tuple) => Expression::TupleAccess(TupleAccessExpression {
|
||||
tuple: Box::new(acc),
|
||||
index: PositiveNumber::from(tuple.number),
|
||||
span: Span::from(tuple.span.clone()),
|
||||
}),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarBinaryExpression<'ast>> for Expression {
|
||||
fn from(expression: GrammarBinaryExpression<'ast>) -> Self {
|
||||
use GrammarBinaryOperation::*;
|
||||
let operator = match expression.operation {
|
||||
Or => BinaryOperation::Or,
|
||||
And => BinaryOperation::And,
|
||||
Eq => BinaryOperation::Eq,
|
||||
Ne => BinaryOperation::Ne,
|
||||
Ge => BinaryOperation::Ge,
|
||||
Gt => BinaryOperation::Gt,
|
||||
Le => BinaryOperation::Le,
|
||||
Lt => BinaryOperation::Lt,
|
||||
Add => BinaryOperation::Add,
|
||||
Sub => BinaryOperation::Sub,
|
||||
Mul => BinaryOperation::Mul,
|
||||
Div => BinaryOperation::Div,
|
||||
Pow => BinaryOperation::Pow,
|
||||
};
|
||||
Expression::Binary(BinaryExpression {
|
||||
left: Box::new(Expression::from(expression.left)),
|
||||
right: Box::new(Expression::from(expression.right)),
|
||||
op: operator,
|
||||
span: Span::from(expression.span),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarTernaryExpression<'ast>> for Expression {
|
||||
fn from(expression: GrammarTernaryExpression<'ast>) -> Self {
|
||||
Expression::Ternary(TernaryExpression {
|
||||
condition: Box::new(Expression::from(expression.first)),
|
||||
if_true: Box::new(Expression::from(expression.second)),
|
||||
if_false: Box::new(Expression::from(expression.third)),
|
||||
span: Span::from(expression.span),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarArrayInlineExpression<'ast>> for Expression {
|
||||
fn from(array: GrammarArrayInlineExpression<'ast>) -> Self {
|
||||
Expression::ArrayInline(ArrayInlineExpression {
|
||||
elements: array.expressions.into_iter().map(SpreadOrExpression::from).collect(),
|
||||
span: Span::from(array.span),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<ArrayInitializerExpression<'ast>> for Expression {
|
||||
fn from(array: ArrayInitializerExpression<'ast>) -> Self {
|
||||
Expression::ArrayInit(ArrayInitExpression {
|
||||
element: Box::new(Expression::from(array.expression)),
|
||||
dimensions: ArrayDimensions::from(array.dimensions),
|
||||
span: Span::from(array.span),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<TupleExpression<'ast>> for Expression {
|
||||
fn from(tuple: TupleExpression<'ast>) -> Self {
|
||||
Expression::TupleInit(TupleInitExpression {
|
||||
elements: tuple.expressions.into_iter().map(Expression::from).collect(),
|
||||
span: Span::from(tuple.span),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<Value<'ast>> for Expression {
|
||||
fn from(value: Value<'ast>) -> Self {
|
||||
match value {
|
||||
Value::Address(address) => Expression::from(address),
|
||||
Value::Boolean(boolean) => Expression::from(boolean),
|
||||
Value::Field(field) => Expression::from(field),
|
||||
Value::Group(group) => Expression::from(group),
|
||||
Value::Implicit(number) => Expression::from(number),
|
||||
Value::Integer(integer) => Expression::from(integer),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarUnaryExpression<'ast>> for Expression {
|
||||
fn from(expression: GrammarUnaryExpression<'ast>) -> Self {
|
||||
use GrammarUnaryOperation::*;
|
||||
let operator = match expression.operation {
|
||||
Not(_) => UnaryOperation::Not,
|
||||
Negate(_) => UnaryOperation::Negate,
|
||||
};
|
||||
Expression::Unary(UnaryExpression {
|
||||
inner: Box::new(Expression::from(expression.expression)),
|
||||
op: operator,
|
||||
span: Span::from(expression.span),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<AddressValue<'ast>> for Expression {
|
||||
fn from(address: AddressValue<'ast>) -> Self {
|
||||
Expression::Value(ValueExpression::Address(
|
||||
address.address.value,
|
||||
Span::from(address.span),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<BooleanValue<'ast>> for Expression {
|
||||
fn from(boolean: BooleanValue<'ast>) -> Self {
|
||||
Expression::Value(ValueExpression::Boolean(boolean.value, Span::from(boolean.span)))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<FieldValue<'ast>> for Expression {
|
||||
fn from(field: FieldValue<'ast>) -> Self {
|
||||
Expression::Value(ValueExpression::Field(field.number.to_string(), Span::from(field.span)))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarGroupValue<'ast>> for Expression {
|
||||
fn from(ast_group: GrammarGroupValue<'ast>) -> Self {
|
||||
Expression::Value(ValueExpression::Group(Box::new(GroupValue::from(ast_group))))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarNumber<'ast>> for Expression {
|
||||
fn from(number: GrammarNumber<'ast>) -> Self {
|
||||
let (value, span) = match number {
|
||||
GrammarNumber::Positive(number) => (number.value, number.span),
|
||||
GrammarNumber::Negative(number) => (number.value, number.span),
|
||||
};
|
||||
|
||||
Expression::Value(ValueExpression::Implicit(value, Span::from(span)))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<IntegerValue<'ast>> for Expression {
|
||||
fn from(integer: IntegerValue<'ast>) -> Self {
|
||||
let span = Span::from(integer.span().clone());
|
||||
let (type_, value) = match integer {
|
||||
IntegerValue::Signed(integer) => {
|
||||
let type_ = IntegerType::from(integer.type_);
|
||||
let number = match integer.number {
|
||||
GrammarNumber::Negative(number) => number.value,
|
||||
GrammarNumber::Positive(number) => number.value,
|
||||
};
|
||||
|
||||
(type_, number)
|
||||
}
|
||||
IntegerValue::Unsigned(integer) => {
|
||||
let type_ = IntegerType::from(integer.type_);
|
||||
let number = integer.number.value;
|
||||
|
||||
(type_, number)
|
||||
}
|
||||
};
|
||||
|
||||
Expression::Value(ValueExpression::Integer(type_, value, span))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<TupleAccess<'ast>> for Expression {
|
||||
fn from(tuple: TupleAccess<'ast>) -> Self {
|
||||
Expression::Value(ValueExpression::Implicit(
|
||||
tuple.number.to_string(),
|
||||
Span::from(tuple.span),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarIdentifier<'ast>> for Expression {
|
||||
fn from(identifier: GrammarIdentifier<'ast>) -> Self {
|
||||
Expression::Identifier(Identifier::from(identifier))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Identifier> for Expression {
|
||||
fn from(identifier: Identifier) -> Self {
|
||||
Expression::Identifier(identifier)
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ use super::*;
|
||||
pub enum UnaryOperation {
|
||||
Not,
|
||||
Negate,
|
||||
BitNot,
|
||||
}
|
||||
|
||||
impl AsRef<str> for UnaryOperation {
|
||||
@ -27,6 +28,7 @@ impl AsRef<str> for UnaryOperation {
|
||||
match self {
|
||||
UnaryOperation::Not => "!",
|
||||
UnaryOperation::Negate => "-",
|
||||
UnaryOperation::BitNot => "~",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,14 +14,14 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{Block, FunctionInput, Identifier, Node, Span, Type};
|
||||
use leo_grammar::functions::Function as GrammarFunction;
|
||||
use crate::{Annotation, Block, FunctionInput, Identifier, Node, Span, Type};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
pub struct Function {
|
||||
pub annotations: Vec<Annotation>,
|
||||
pub identifier: Identifier,
|
||||
pub input: Vec<FunctionInput>,
|
||||
pub output: Option<Type>,
|
||||
@ -37,24 +37,6 @@ impl PartialEq for Function {
|
||||
|
||||
impl Eq for Function {}
|
||||
|
||||
impl<'ast> From<GrammarFunction<'ast>> for Function {
|
||||
fn from(function: GrammarFunction<'ast>) -> Self {
|
||||
let function_name = Identifier::from(function.identifier);
|
||||
|
||||
let parameters = function.parameters.into_iter().map(FunctionInput::from).collect();
|
||||
let returns = function.returns.map(Type::from);
|
||||
let block = Block::from(function.block);
|
||||
|
||||
Function {
|
||||
identifier: function_name,
|
||||
input: parameters,
|
||||
output: returns,
|
||||
block,
|
||||
span: Span::from(function.span),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Function {
|
||||
pub fn get_name(&self) -> &str {
|
||||
&self.identifier.name
|
||||
|
@ -15,7 +15,6 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{Identifier, Node, Span, Type};
|
||||
use leo_grammar::functions::FunctionInput as GrammarFunctionInput;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
@ -29,18 +28,6 @@ pub struct FunctionInputVariable {
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarFunctionInput<'ast>> for FunctionInputVariable {
|
||||
fn from(parameter: GrammarFunctionInput<'ast>) -> Self {
|
||||
FunctionInputVariable {
|
||||
identifier: Identifier::from(parameter.identifier),
|
||||
const_: parameter.const_.is_some(),
|
||||
mutable: parameter.mutable.is_some(),
|
||||
type_: Type::from(parameter.type_),
|
||||
span: Span::from(parameter.span),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FunctionInputVariable {
|
||||
fn format(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
// mut var: bool
|
||||
|
@ -15,7 +15,6 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{FunctionInputVariable, InputKeyword, MutSelfKeyword, Node, SelfKeyword, Span};
|
||||
use leo_grammar::functions::input::Input as GrammarInput;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
@ -29,19 +28,6 @@ pub enum FunctionInput {
|
||||
Variable(FunctionInputVariable),
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarInput<'ast>> for FunctionInput {
|
||||
fn from(input: GrammarInput<'ast>) -> Self {
|
||||
match input {
|
||||
GrammarInput::InputKeyword(keyword) => FunctionInput::InputKeyword(InputKeyword::from(keyword)),
|
||||
GrammarInput::SelfKeyword(keyword) => FunctionInput::SelfKeyword(SelfKeyword::from(keyword)),
|
||||
GrammarInput::MutSelfKeyword(keyword) => FunctionInput::MutSelfKeyword(MutSelfKeyword::from(keyword)),
|
||||
GrammarInput::FunctionInput(function_input) => {
|
||||
FunctionInput::Variable(FunctionInputVariable::from(function_input))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FunctionInput {
|
||||
///
|
||||
/// Returns `true` if the function input is the `self` or `mut self` keyword.
|
||||
|
@ -19,6 +19,3 @@ pub use function::*;
|
||||
|
||||
pub mod input;
|
||||
pub use input::*;
|
||||
|
||||
pub mod test_function;
|
||||
pub use test_function::*;
|
||||
|
@ -1,35 +0,0 @@
|
||||
// Copyright (C) 2019-2021 Aleo Systems Inc.
|
||||
// This file is part of the Leo library.
|
||||
|
||||
// The Leo library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// The Leo library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{Function, Identifier};
|
||||
use leo_grammar::functions::TestFunction as GrammarTestFunction;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct TestFunction {
|
||||
pub function: Function,
|
||||
pub input_file: Option<Identifier>,
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarTestFunction<'ast>> for TestFunction {
|
||||
fn from(test: GrammarTestFunction) -> Self {
|
||||
TestFunction {
|
||||
function: Function::from(test.function),
|
||||
input_file: None, // pass custom input file with `@context` annotation
|
||||
}
|
||||
}
|
||||
}
|
@ -15,13 +15,6 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::common::span::Span;
|
||||
use leo_grammar::values::{
|
||||
GroupCoordinate as GrammarGroupCoordinate,
|
||||
Inferred as GrammarInferred,
|
||||
NumberValue as GrammarNumberValue,
|
||||
SignHigh as GrammarSignHigh,
|
||||
SignLow as GrammarSignLow,
|
||||
};
|
||||
use leo_input::values::{
|
||||
GroupCoordinate as InputGroupCoordinate,
|
||||
Inferred as InputInferred,
|
||||
@ -41,17 +34,6 @@ pub enum GroupCoordinate {
|
||||
Inferred,
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarGroupCoordinate<'ast>> for GroupCoordinate {
|
||||
fn from(coordinate: GrammarGroupCoordinate<'ast>) -> Self {
|
||||
match coordinate {
|
||||
GrammarGroupCoordinate::Number(number) => GroupCoordinate::from(number),
|
||||
GrammarGroupCoordinate::SignHigh(sign_high) => GroupCoordinate::from(sign_high),
|
||||
GrammarGroupCoordinate::SignLow(sign_low) => GroupCoordinate::from(sign_low),
|
||||
GrammarGroupCoordinate::Inferred(inferred) => GroupCoordinate::from(inferred),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<InputGroupCoordinate<'ast>> for GroupCoordinate {
|
||||
fn from(coordinate: InputGroupCoordinate<'ast>) -> Self {
|
||||
match coordinate {
|
||||
@ -74,33 +56,6 @@ impl fmt::Display for GroupCoordinate {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarNumberValue<'ast>> for GroupCoordinate {
|
||||
fn from(number: GrammarNumberValue<'ast>) -> Self {
|
||||
let value = number.to_string();
|
||||
let span = Span::from(number.span().clone());
|
||||
|
||||
GroupCoordinate::Number(value, span)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarSignHigh<'ast>> for GroupCoordinate {
|
||||
fn from(_sign: GrammarSignHigh<'ast>) -> Self {
|
||||
GroupCoordinate::SignHigh
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarSignLow<'ast>> for GroupCoordinate {
|
||||
fn from(_sign: GrammarSignLow<'ast>) -> Self {
|
||||
GroupCoordinate::SignLow
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarInferred<'ast>> for GroupCoordinate {
|
||||
fn from(_sign: GrammarInferred<'ast>) -> Self {
|
||||
GroupCoordinate::Inferred
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<InputNumberValue<'ast>> for GroupCoordinate {
|
||||
fn from(number: InputNumberValue<'ast>) -> Self {
|
||||
let value = number.to_string();
|
||||
|
@ -15,11 +15,6 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{common::span::Span, groups::GroupCoordinate};
|
||||
use leo_grammar::values::{
|
||||
GroupRepresentation as GrammarGroupRepresentation,
|
||||
GroupTuple as GrammarGroupTuple,
|
||||
GroupValue as GrammarGroupValue,
|
||||
};
|
||||
use leo_input::values::{
|
||||
GroupRepresentation as InputGroupRepresentation,
|
||||
GroupTuple as InputGroupTuple,
|
||||
@ -51,17 +46,6 @@ impl GroupValue {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarGroupValue<'ast>> for GroupValue {
|
||||
fn from(ast_group: GrammarGroupValue) -> Self {
|
||||
let span = Span::from(ast_group.span);
|
||||
|
||||
match ast_group.value {
|
||||
GrammarGroupRepresentation::Single(number) => GroupValue::Single(number.to_string(), span),
|
||||
GrammarGroupRepresentation::Tuple(tuple) => GroupValue::Tuple(GroupTuple::from(tuple)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<InputGroupValue<'ast>> for GroupValue {
|
||||
fn from(ast_group: InputGroupValue) -> Self {
|
||||
let span = Span::from(ast_group.span);
|
||||
@ -89,19 +73,6 @@ pub struct GroupTuple {
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarGroupTuple<'ast>> for GroupTuple {
|
||||
fn from(ast_group: GrammarGroupTuple<'ast>) -> Self {
|
||||
let ast_x = ast_group.x;
|
||||
let ast_y = ast_group.y;
|
||||
|
||||
Self {
|
||||
x: GroupCoordinate::from(ast_x),
|
||||
y: GroupCoordinate::from(ast_y),
|
||||
span: Span::from(ast_group.span),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<InputGroupTuple<'ast>> for GroupTuple {
|
||||
fn from(ast_group: InputGroupTuple<'ast>) -> Self {
|
||||
let ast_x = ast_group.x;
|
||||
|
@ -15,7 +15,6 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{PackageOrPackages, Span};
|
||||
use leo_grammar::imports::Import as GrammarImport;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
@ -39,15 +38,6 @@ impl ImportStatement {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarImport<'ast>> for ImportStatement {
|
||||
fn from(import: GrammarImport<'ast>) -> Self {
|
||||
ImportStatement {
|
||||
package_or_packages: PackageOrPackages::from(import.package_or_packages),
|
||||
span: Span::from(import.span),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ImportStatement {
|
||||
fn format(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "import {};", self.package_or_packages)
|
||||
|
@ -15,7 +15,6 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{Identifier, Span};
|
||||
use leo_grammar::imports::ImportSymbol as GrammarImportSymbol;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
@ -27,16 +26,6 @@ pub struct ImportSymbol {
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarImportSymbol<'ast>> for ImportSymbol {
|
||||
fn from(symbol: GrammarImportSymbol<'ast>) -> Self {
|
||||
ImportSymbol {
|
||||
symbol: Identifier::from(symbol.value),
|
||||
alias: symbol.alias.map(Identifier::from),
|
||||
span: Span::from(symbol.span),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ImportSymbol {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
if self.alias.is_some() {
|
||||
|
@ -15,7 +15,6 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{common::Identifier, PackageAccess, Span};
|
||||
use leo_grammar::imports::Package as GrammarPackage;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
@ -27,16 +26,6 @@ pub struct Package {
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarPackage<'ast>> for Package {
|
||||
fn from(package: GrammarPackage<'ast>) -> Self {
|
||||
Package {
|
||||
name: Identifier::from(package.name),
|
||||
access: PackageAccess::from(package.access),
|
||||
span: Span::from(package.span),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Package {
|
||||
fn format(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}.{}", self.name, self.access)
|
||||
|
@ -14,8 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{ImportSymbol, Package, Packages, Span};
|
||||
use leo_grammar::imports::PackageAccess as GrammarPackageAccess;
|
||||
use crate::{ImportSymbol, Node, Package, Packages, Span};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
@ -28,13 +27,22 @@ pub enum PackageAccess {
|
||||
Multiple(Packages),
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarPackageAccess<'ast>> for PackageAccess {
|
||||
fn from(access: GrammarPackageAccess<'ast>) -> Self {
|
||||
match access {
|
||||
GrammarPackageAccess::Star(star) => PackageAccess::Star(Span::from(star.span)),
|
||||
GrammarPackageAccess::SubPackage(package) => PackageAccess::SubPackage(Box::new(Package::from(*package))),
|
||||
GrammarPackageAccess::Symbol(symbol) => PackageAccess::Symbol(ImportSymbol::from(symbol)),
|
||||
GrammarPackageAccess::Multiple(packages) => PackageAccess::Multiple(Packages::from(packages)),
|
||||
impl Node for PackageAccess {
|
||||
fn span(&self) -> &Span {
|
||||
match self {
|
||||
PackageAccess::Star(span) => span,
|
||||
PackageAccess::SubPackage(package) => &package.span,
|
||||
PackageAccess::Symbol(package) => &package.span,
|
||||
PackageAccess::Multiple(package) => &package.span,
|
||||
}
|
||||
}
|
||||
|
||||
fn set_span(&mut self, span: Span) {
|
||||
match self {
|
||||
PackageAccess::Star(package) => *package = span,
|
||||
PackageAccess::SubPackage(package) => package.span = span,
|
||||
PackageAccess::Symbol(package) => package.span = span,
|
||||
PackageAccess::Multiple(package) => package.span = span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,8 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{Package, Packages};
|
||||
use leo_grammar::imports::PackageOrPackages as GrammarPackageOrPackages;
|
||||
use crate::{Node, Package, Packages, Span};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
@ -26,15 +25,6 @@ pub enum PackageOrPackages {
|
||||
Packages(Packages),
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarPackageOrPackages<'ast>> for PackageOrPackages {
|
||||
fn from(package_or_packages: GrammarPackageOrPackages<'ast>) -> Self {
|
||||
match package_or_packages {
|
||||
GrammarPackageOrPackages::Package(package) => PackageOrPackages::Package(Package::from(package)),
|
||||
GrammarPackageOrPackages::Packages(packages) => PackageOrPackages::Packages(Packages::from(packages)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PackageOrPackages {
|
||||
fn format(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
@ -64,3 +54,19 @@ impl fmt::Display for PackageOrPackages {
|
||||
self.format(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl Node for PackageOrPackages {
|
||||
fn span(&self) -> &Span {
|
||||
match self {
|
||||
PackageOrPackages::Package(package) => &package.span,
|
||||
PackageOrPackages::Packages(packages) => &packages.span,
|
||||
}
|
||||
}
|
||||
|
||||
fn set_span(&mut self, span: Span) {
|
||||
match self {
|
||||
PackageOrPackages::Package(package) => package.span = span,
|
||||
PackageOrPackages::Packages(packages) => packages.span = span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,6 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{common::Identifier, PackageAccess, Span};
|
||||
use leo_grammar::imports::Packages as GrammarPackages;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
@ -27,16 +26,6 @@ pub struct Packages {
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarPackages<'ast>> for Packages {
|
||||
fn from(packages: GrammarPackages<'ast>) -> Self {
|
||||
Packages {
|
||||
name: Identifier::from(packages.name),
|
||||
accesses: packages.accesses.into_iter().map(PackageAccess::from).collect(),
|
||||
span: Span::from(packages.span),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Packages {
|
||||
fn format(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}.(", self.name)?;
|
||||
|
@ -114,7 +114,7 @@ impl InputValue {
|
||||
let array_dimensions_type = ArrayDimensions::from(array_type.dimensions.clone());
|
||||
|
||||
// Convert the array dimensions to usize.
|
||||
let array_dimensions = parse_array_dimensions(array_dimensions_type, array_type.span.clone())?;
|
||||
let array_dimensions = parse_array_dimensions(array_dimensions_type, &array_type.span)?;
|
||||
|
||||
// Return an error if the outer array dimension does not equal the number of array elements.
|
||||
if array_dimensions[0] != inline.expressions.len() {
|
||||
@ -146,7 +146,7 @@ impl InputValue {
|
||||
initializer: ArrayInitializerExpression,
|
||||
) -> Result<Self, InputParserError> {
|
||||
let array_dimensions_type = ArrayDimensions::from(initializer.dimensions.clone());
|
||||
let array_dimensions = parse_array_dimensions(array_dimensions_type, array_type.span.clone())?;
|
||||
let array_dimensions = parse_array_dimensions(array_dimensions_type, &array_type.span)?;
|
||||
|
||||
if array_dimensions.len() > 1 {
|
||||
// The expression is an array initializer with tuple syntax
|
||||
@ -169,7 +169,7 @@ impl InputValue {
|
||||
return Err(InputParserError::array_init_length(
|
||||
array_dimensions,
|
||||
initializer_dimensions,
|
||||
initializer.span,
|
||||
&initializer.span,
|
||||
));
|
||||
}
|
||||
|
||||
@ -199,7 +199,7 @@ impl InputValue {
|
||||
let array_dimensions_type = ArrayDimensions::from(array_type.dimensions.clone());
|
||||
|
||||
// Convert the array dimensions to usize.
|
||||
let array_dimensions = parse_array_dimensions(array_dimensions_type, array_type.span.clone())?;
|
||||
let array_dimensions = parse_array_dimensions(array_dimensions_type, &array_type.span)?;
|
||||
|
||||
let current_array_dimension = array_dimensions[0];
|
||||
let current_initializer_dimension = initializer_dimensions[0];
|
||||
@ -209,7 +209,7 @@ impl InputValue {
|
||||
return Err(InputParserError::array_init_length(
|
||||
array_dimensions,
|
||||
initializer_dimensions,
|
||||
initializer.span,
|
||||
&initializer.span,
|
||||
));
|
||||
}
|
||||
|
||||
@ -235,11 +235,7 @@ impl InputValue {
|
||||
let num_values = tuple.expressions.len();
|
||||
|
||||
if num_types != num_values {
|
||||
return Err(InputParserError::tuple_length(
|
||||
num_types,
|
||||
num_values,
|
||||
tuple_type.span.clone(),
|
||||
));
|
||||
return Err(InputParserError::tuple_length(num_types, num_values, &tuple_type.span));
|
||||
}
|
||||
|
||||
let mut values = Vec::with_capacity(tuple_type.types_.len());
|
||||
@ -260,7 +256,7 @@ impl InputValue {
|
||||
/// is successful, the `usize` value is appended to the return vector. If parsing fails, an error
|
||||
/// is returned.
|
||||
///
|
||||
fn parse_array_dimensions(array_dimensions_type: ArrayDimensions, span: Span) -> Result<Vec<usize>, InputParserError> {
|
||||
fn parse_array_dimensions(array_dimensions_type: ArrayDimensions, span: &Span) -> Result<Vec<usize>, InputParserError> {
|
||||
// Convert the array dimensions to usize.
|
||||
let mut array_dimensions = Vec::with_capacity(array_dimensions_type.0.len());
|
||||
|
||||
@ -271,7 +267,7 @@ fn parse_array_dimensions(array_dimensions_type: ArrayDimensions, span: Span) ->
|
||||
// Convert the string to usize.
|
||||
let dimension_usize = match dimension_string.parse::<usize>() {
|
||||
Ok(dimension_usize) => dimension_usize,
|
||||
Err(_) => return Err(InputParserError::array_index(dimension_string, span.clone())),
|
||||
Err(_) => return Err(InputParserError::array_index(dimension_string, span)),
|
||||
};
|
||||
|
||||
// Collect dimension usize values.
|
||||
@ -292,7 +288,7 @@ fn fetch_nested_array_type_dimensions(
|
||||
let array_dimensions_type = ArrayDimensions::from(array_type.dimensions.clone());
|
||||
|
||||
// Convert the array dimensions to usize.
|
||||
let mut current_dimension = parse_array_dimensions(array_dimensions_type, array_type.span.clone())?;
|
||||
let mut current_dimension = parse_array_dimensions(array_dimensions_type, &array_type.span)?;
|
||||
|
||||
array_dimensions.append(&mut current_dimension);
|
||||
|
||||
|
@ -19,9 +19,6 @@
|
||||
//! This module contains the [`Ast`] type, a wrapper around the [`Program`] type.
|
||||
//! The [`Ast`] type is intended to be parsed and modified by different passes
|
||||
//! of the Leo compiler. The Leo compiler can generate a set of R1CS constraints from any [`Ast`].
|
||||
#[macro_use]
|
||||
extern crate thiserror;
|
||||
|
||||
pub mod annotation;
|
||||
pub use self::annotation::*;
|
||||
|
||||
@ -61,8 +58,6 @@ pub use self::types::*;
|
||||
mod node;
|
||||
pub use node::*;
|
||||
|
||||
use leo_grammar::Grammar;
|
||||
|
||||
/// The abstract syntax tree (AST) for a Leo program.
|
||||
///
|
||||
/// The [`Ast`] type represents a Leo program as a series of recursive data types.
|
||||
@ -75,11 +70,9 @@ pub struct Ast {
|
||||
}
|
||||
|
||||
impl Ast {
|
||||
/// Creates a new AST from a given program name and grammar tree.
|
||||
pub fn new<'ast>(program_name: &str, grammar: &Grammar<'ast>) -> Result<Self, AstError> {
|
||||
Ok(Self {
|
||||
ast: Program::from(program_name, grammar.as_repr())?,
|
||||
})
|
||||
/// Creates a new AST from a given program tree.
|
||||
pub fn new(program: Program) -> Self {
|
||||
Self { ast: program }
|
||||
}
|
||||
|
||||
/// Returns a reference to the inner program AST representation.
|
||||
@ -87,6 +80,10 @@ impl Ast {
|
||||
&self.ast
|
||||
}
|
||||
|
||||
pub fn into_repr(self) -> Program {
|
||||
self.ast
|
||||
}
|
||||
|
||||
/// Serializes the ast into a JSON string.
|
||||
pub fn to_json_string(&self) -> Result<String, serde_json::Error> {
|
||||
serde_json::to_string_pretty(&self.ast)
|
||||
@ -98,3 +95,9 @@ impl Ast {
|
||||
Ok(Self { ast })
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<Program> for Ast {
|
||||
fn as_ref(&self) -> &Program {
|
||||
&self.ast
|
||||
}
|
||||
}
|
||||
|
@ -1,71 +0,0 @@
|
||||
// Copyright (C) 2019-2021 Aleo Systems Inc.
|
||||
// This file is part of the Leo library.
|
||||
|
||||
// The Leo library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// The Leo library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use leo_ast::{Ast, AstError};
|
||||
use leo_grammar::Grammar;
|
||||
use std::{env, fs, path::Path};
|
||||
|
||||
fn to_leo_tree(filepath: &Path) -> Result<String, AstError> {
|
||||
// Loads the Leo code as a string from the given file path.
|
||||
let program_filepath = filepath.to_path_buf();
|
||||
let program_string = Grammar::load_file(&program_filepath)?;
|
||||
|
||||
// Parses the Leo file and constructs a pest ast.
|
||||
let ast = Grammar::new(&program_filepath, &program_string)?;
|
||||
|
||||
// Parse the pest ast and constructs a ast.
|
||||
let leo_ast = Ast::new("leo_tree", &ast)?;
|
||||
|
||||
let serialized_leo_ast = Ast::to_json_string(&leo_ast)?;
|
||||
|
||||
Ok(serialized_leo_ast)
|
||||
}
|
||||
|
||||
fn main() -> Result<(), AstError> {
|
||||
// Parse the command-line arguments as strings.
|
||||
let cli_arguments = env::args().collect::<Vec<String>>();
|
||||
|
||||
// Check that the correct number of command-line arguments were passed in.
|
||||
if cli_arguments.len() < 2 || cli_arguments.len() > 3 {
|
||||
eprintln!("Warning - an invalid number of command-line arguments were provided.");
|
||||
println!(
|
||||
"\nCommand-line usage:\n\n\tleo_ast {{PATH/TO/INPUT_FILENAME}}.leo {{PATH/TO/OUTPUT_DIRECTORY (optional)}}\n"
|
||||
);
|
||||
return Ok(()); // Exit innocently
|
||||
}
|
||||
|
||||
// Construct the input filepath.
|
||||
let input_filepath = Path::new(&cli_arguments[1]);
|
||||
|
||||
// Construct the serialized syntax tree.
|
||||
let serialized_leo_tree = to_leo_tree(&input_filepath)?;
|
||||
println!("{}", serialized_leo_tree);
|
||||
|
||||
// Determine the output directory.
|
||||
let output_directory = match cli_arguments.len() == 3 {
|
||||
true => format!(
|
||||
"{}/{}.json",
|
||||
cli_arguments[2],
|
||||
input_filepath.file_stem().unwrap().to_str().unwrap()
|
||||
),
|
||||
false => format!("./{}.json", input_filepath.file_stem().unwrap().to_str().unwrap()),
|
||||
};
|
||||
|
||||
// Write the serialized syntax tree to the output directory.
|
||||
fs::write(Path::new(&output_directory), serialized_leo_tree)?;
|
||||
|
||||
Ok(())
|
||||
}
|
@ -17,17 +17,7 @@
|
||||
//! A Leo program consists of import, circuit, and function definitions.
|
||||
//! Each defined type consists of ast statements and expressions.
|
||||
|
||||
use crate::{
|
||||
load_annotation,
|
||||
Circuit,
|
||||
DeprecatedError,
|
||||
Function,
|
||||
FunctionInput,
|
||||
Identifier,
|
||||
ImportStatement,
|
||||
TestFunction,
|
||||
};
|
||||
use leo_grammar::{definitions::Definition, files::File};
|
||||
use crate::{Circuit, Function, FunctionInput, Identifier, ImportStatement};
|
||||
|
||||
use indexmap::IndexMap;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -41,7 +31,12 @@ pub struct Program {
|
||||
pub imports: Vec<ImportStatement>,
|
||||
pub circuits: IndexMap<Identifier, Circuit>,
|
||||
pub functions: IndexMap<Identifier, Function>,
|
||||
pub tests: IndexMap<Identifier, TestFunction>,
|
||||
}
|
||||
|
||||
impl AsRef<Program> for Program {
|
||||
fn as_ref(&self) -> &Program {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Program {
|
||||
@ -60,80 +55,10 @@ impl fmt::Display for Program {
|
||||
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 {
|
||||
//! Logic to convert from an abstract syntax tree (ast) representation to a Leo program.
|
||||
pub fn from(program_name: &str, program_ast: &File<'ast>) -> Result<Self, DeprecatedError> {
|
||||
let mut imports = vec![];
|
||||
let mut circuits = IndexMap::new();
|
||||
let mut functions = IndexMap::new();
|
||||
let mut tests = IndexMap::new();
|
||||
let mut expected_input = vec![];
|
||||
|
||||
program_ast
|
||||
.definitions
|
||||
.to_owned()
|
||||
.into_iter()
|
||||
// Use of Infallible to say we never expect an Some(Ok(...))
|
||||
.find_map::<Result<std::convert::Infallible, _>, _>(|definition| match definition {
|
||||
Definition::Import(import) => {
|
||||
imports.push(ImportStatement::from(import));
|
||||
None
|
||||
}
|
||||
Definition::Circuit(circuit) => {
|
||||
circuits.insert(Identifier::from(circuit.identifier.clone()), Circuit::from(circuit));
|
||||
None
|
||||
}
|
||||
Definition::Function(function_def) => {
|
||||
let function = Function::from(function_def);
|
||||
if function.identifier.name.eq(MAIN_FUNCTION_NAME) {
|
||||
expected_input = function.input.clone();
|
||||
}
|
||||
functions.insert(function.identifier.clone(), function);
|
||||
None
|
||||
}
|
||||
Definition::Deprecated(deprecated) => {
|
||||
Some(Err(DeprecatedError::from(deprecated)))
|
||||
}
|
||||
Definition::Annotated(annotated_definition) => {
|
||||
let loaded_annotation = load_annotation(
|
||||
annotated_definition,
|
||||
&mut imports,
|
||||
&mut circuits,
|
||||
&mut functions,
|
||||
&mut tests,
|
||||
&mut expected_input,
|
||||
);
|
||||
|
||||
match loaded_annotation {
|
||||
Ok(_) => None,
|
||||
Err(deprecated_err) => Some(Err(deprecated_err))
|
||||
}
|
||||
}
|
||||
})
|
||||
.transpose()?;
|
||||
|
||||
Ok(Self {
|
||||
name: program_name.to_string(),
|
||||
expected_input,
|
||||
imports,
|
||||
circuits,
|
||||
functions,
|
||||
tests,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Program {
|
||||
pub fn new(name: String) -> Self {
|
||||
Self {
|
||||
@ -142,7 +67,6 @@ impl Program {
|
||||
imports: vec![],
|
||||
circuits: IndexMap::new(),
|
||||
functions: IndexMap::new(),
|
||||
tests: IndexMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,10 +15,6 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{Expression, Identifier, PositiveNumber, Span};
|
||||
use leo_grammar::{
|
||||
access::{ArrayAccess, AssigneeAccess as GrammarAssigneeAccess},
|
||||
common::{Assignee as GrammarAssignee, Range, RangeOrExpression},
|
||||
};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
@ -31,25 +27,6 @@ pub enum AssigneeAccess {
|
||||
Member(Identifier),
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarAssigneeAccess<'ast>> for AssigneeAccess {
|
||||
fn from(access: GrammarAssigneeAccess<'ast>) -> Self {
|
||||
match access {
|
||||
GrammarAssigneeAccess::Array(ArrayAccess {
|
||||
expression: RangeOrExpression::Range(Range { from, to, .. }),
|
||||
..
|
||||
}) => AssigneeAccess::ArrayRange(from.map(Expression::from), to.map(Expression::from)),
|
||||
GrammarAssigneeAccess::Array(ArrayAccess {
|
||||
expression: RangeOrExpression::Expression(index),
|
||||
..
|
||||
}) => AssigneeAccess::ArrayIndex(Expression::from(index)),
|
||||
GrammarAssigneeAccess::Tuple(tuple) => {
|
||||
AssigneeAccess::Tuple(PositiveNumber::from(tuple.number), Span::from(tuple.span))
|
||||
}
|
||||
GrammarAssigneeAccess::Member(member) => AssigneeAccess::Member(Identifier::from(member.identifier)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Definition assignee: v, arr[0..2], Point p.x
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct Assignee {
|
||||
@ -65,20 +42,6 @@ impl Assignee {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarAssignee<'ast>> for Assignee {
|
||||
fn from(assignee: GrammarAssignee<'ast>) -> Self {
|
||||
Assignee {
|
||||
identifier: Identifier::from(assignee.name),
|
||||
accesses: assignee
|
||||
.accesses
|
||||
.into_iter()
|
||||
.map(AssigneeAccess::from)
|
||||
.collect::<Vec<_>>(),
|
||||
span: Span::from(assignee.span),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Assignee {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", self.identifier)?;
|
||||
|
@ -16,8 +16,6 @@
|
||||
|
||||
use crate::{Expression, Node, Span};
|
||||
|
||||
pub use leo_grammar::operations::AssignOperation as GrammarAssignOperation;
|
||||
use leo_grammar::statements::AssignStatement as GrammarAssignStatement;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
@ -32,6 +30,15 @@ pub enum AssignOperation {
|
||||
Mul,
|
||||
Div,
|
||||
Pow,
|
||||
Or,
|
||||
And,
|
||||
BitOr,
|
||||
BitAnd,
|
||||
BitXor,
|
||||
Shr,
|
||||
ShrSigned,
|
||||
Shl,
|
||||
Mod,
|
||||
}
|
||||
|
||||
impl AsRef<str> for AssignOperation {
|
||||
@ -43,6 +50,15 @@ impl AsRef<str> for AssignOperation {
|
||||
AssignOperation::Mul => "*=",
|
||||
AssignOperation::Div => "/=",
|
||||
AssignOperation::Pow => "**=",
|
||||
AssignOperation::Or => "||=",
|
||||
AssignOperation::And => "&&=",
|
||||
AssignOperation::BitOr => "|=",
|
||||
AssignOperation::BitAnd => "&=",
|
||||
AssignOperation::BitXor => "^=",
|
||||
AssignOperation::Shr => ">>=",
|
||||
AssignOperation::ShrSigned => ">>>=",
|
||||
AssignOperation::Shl => "<<=",
|
||||
AssignOperation::Mod => "%=",
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -61,24 +77,6 @@ impl fmt::Display for AssignStatement {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarAssignStatement<'ast>> for AssignStatement {
|
||||
fn from(statement: GrammarAssignStatement<'ast>) -> Self {
|
||||
AssignStatement {
|
||||
operation: match statement.assign {
|
||||
GrammarAssignOperation::Assign(_) => AssignOperation::Assign,
|
||||
GrammarAssignOperation::AddAssign(_) => AssignOperation::Add,
|
||||
GrammarAssignOperation::SubAssign(_) => AssignOperation::Sub,
|
||||
GrammarAssignOperation::MulAssign(_) => AssignOperation::Mul,
|
||||
GrammarAssignOperation::DivAssign(_) => AssignOperation::Div,
|
||||
GrammarAssignOperation::PowAssign(_) => AssignOperation::Pow,
|
||||
},
|
||||
assignee: Assignee::from(statement.assignee),
|
||||
value: Expression::from(statement.expression),
|
||||
span: Span::from(statement.span),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Node for AssignStatement {
|
||||
fn span(&self) -> &Span {
|
||||
&self.span
|
||||
|
@ -15,7 +15,6 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{Node, Span, Statement};
|
||||
use leo_grammar::statements::Block as GrammarBlock;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
@ -26,15 +25,6 @@ pub struct Block {
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarBlock<'ast>> for Block {
|
||||
fn from(block: GrammarBlock<'ast>) -> Self {
|
||||
Block {
|
||||
statements: block.statements.into_iter().map(Statement::from).collect(),
|
||||
span: Span::from(block.span),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Block {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
writeln!(f, "{{")?;
|
||||
|
@ -15,7 +15,6 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{Block, Expression, Node, Span, Statement};
|
||||
use leo_grammar::statements::{ConditionalNestedOrEndStatement, ConditionalStatement as GrammarConditionalStatement};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
@ -28,25 +27,6 @@ pub struct ConditionalStatement {
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarConditionalStatement<'ast>> for ConditionalStatement {
|
||||
fn from(statement: GrammarConditionalStatement<'ast>) -> Self {
|
||||
ConditionalStatement {
|
||||
condition: Expression::from(statement.condition),
|
||||
block: Block::from(statement.block),
|
||||
next: statement
|
||||
.next
|
||||
.map(|nested_statement| match nested_statement {
|
||||
ConditionalNestedOrEndStatement::Nested(conditional_statement) => {
|
||||
Statement::Conditional(ConditionalStatement::from(*conditional_statement))
|
||||
}
|
||||
ConditionalNestedOrEndStatement::End(block) => Statement::Block(Block::from(block)),
|
||||
})
|
||||
.map(Box::new),
|
||||
span: Span::from(statement.span),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ConditionalStatement {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "if ({}) {}", self.condition, self.block)?;
|
||||
|
@ -14,19 +14,12 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{Expression, FormattedString};
|
||||
use leo_grammar::console::{
|
||||
ConsoleAssert as GrammarConsoleAssert,
|
||||
ConsoleDebug as GrammarConsoleDebug,
|
||||
ConsoleError as GrammarConsoleError,
|
||||
ConsoleFunction as GrammarConsoleFunction,
|
||||
ConsoleLog as GrammarConsoleLog,
|
||||
};
|
||||
use crate::{Expression, FormattedString, Node, Span};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
|
||||
pub enum ConsoleFunction {
|
||||
Assert(Expression),
|
||||
Debug(FormattedString),
|
||||
@ -34,41 +27,6 @@ pub enum ConsoleFunction {
|
||||
Log(FormattedString),
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarConsoleFunction<'ast>> for ConsoleFunction {
|
||||
fn from(console_function: GrammarConsoleFunction<'ast>) -> Self {
|
||||
match console_function {
|
||||
GrammarConsoleFunction::Assert(assert) => ConsoleFunction::from(assert),
|
||||
GrammarConsoleFunction::Debug(debug) => ConsoleFunction::from(debug),
|
||||
GrammarConsoleFunction::Error(error) => ConsoleFunction::from(error),
|
||||
GrammarConsoleFunction::Log(log) => ConsoleFunction::from(log),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarConsoleAssert<'ast>> for ConsoleFunction {
|
||||
fn from(assert: GrammarConsoleAssert<'ast>) -> Self {
|
||||
ConsoleFunction::Assert(Expression::from(assert.expression))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarConsoleDebug<'ast>> for ConsoleFunction {
|
||||
fn from(debug: GrammarConsoleDebug<'ast>) -> Self {
|
||||
ConsoleFunction::Debug(FormattedString::from(debug.string))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarConsoleError<'ast>> for ConsoleFunction {
|
||||
fn from(error: GrammarConsoleError<'ast>) -> Self {
|
||||
ConsoleFunction::Error(FormattedString::from(error.string))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarConsoleLog<'ast>> for ConsoleFunction {
|
||||
fn from(log: GrammarConsoleLog<'ast>) -> Self {
|
||||
ConsoleFunction::Log(FormattedString::from(log.string))
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ConsoleFunction {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
@ -79,3 +37,23 @@ impl fmt::Display for ConsoleFunction {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Node for ConsoleFunction {
|
||||
fn span(&self) -> &Span {
|
||||
match self {
|
||||
ConsoleFunction::Assert(assert) => assert.span(),
|
||||
ConsoleFunction::Debug(formatted) | ConsoleFunction::Error(formatted) | ConsoleFunction::Log(formatted) => {
|
||||
&formatted.span
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn set_span(&mut self, span: Span) {
|
||||
match self {
|
||||
ConsoleFunction::Assert(assert) => assert.set_span(span),
|
||||
ConsoleFunction::Debug(formatted) | ConsoleFunction::Error(formatted) | ConsoleFunction::Log(formatted) => {
|
||||
formatted.set_span(span)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,6 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{ConsoleFunction, Node, Span};
|
||||
use leo_grammar::console::ConsoleFunctionCall as GrammarConsoleFunctionCall;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
@ -26,15 +25,6 @@ pub struct ConsoleStatement {
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarConsoleFunctionCall<'ast>> for ConsoleStatement {
|
||||
fn from(console: GrammarConsoleFunctionCall<'ast>) -> Self {
|
||||
ConsoleStatement {
|
||||
function: ConsoleFunction::from(console.function),
|
||||
span: Span::from(console.span),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ConsoleStatement {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "console.{};", self.function)
|
||||
|
@ -15,7 +15,6 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{Node, Span};
|
||||
use leo_grammar::console::FormattedContainer as GrammarFormattedContainer;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
@ -25,14 +24,6 @@ pub struct FormattedContainer {
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarFormattedContainer<'ast>> for FormattedContainer {
|
||||
fn from(container: GrammarFormattedContainer<'ast>) -> Self {
|
||||
Self {
|
||||
span: Span::from(container.span),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for FormattedContainer {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{{}}")
|
||||
|
@ -14,39 +14,38 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{Expression, FormattedContainer, Node, Span};
|
||||
use leo_grammar::console::FormattedString as GrammarFormattedString;
|
||||
use crate::{Expression, Node, Span};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
|
||||
pub enum FormattedStringPart {
|
||||
Const(String),
|
||||
Container,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
|
||||
pub struct FormattedString {
|
||||
pub string: String,
|
||||
pub containers: Vec<FormattedContainer>,
|
||||
pub parts: Vec<FormattedStringPart>,
|
||||
pub parameters: Vec<Expression>,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarFormattedString<'ast>> for FormattedString {
|
||||
fn from(formatted: GrammarFormattedString<'ast>) -> Self {
|
||||
let string = formatted.string;
|
||||
let span = Span::from(formatted.span);
|
||||
let containers = formatted.containers.into_iter().map(FormattedContainer::from).collect();
|
||||
let parameters = formatted.parameters.into_iter().map(Expression::from).collect();
|
||||
|
||||
Self {
|
||||
string,
|
||||
containers,
|
||||
parameters,
|
||||
span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for FormattedString {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", self.string)
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
self.parts
|
||||
.iter()
|
||||
.map(|x| match x {
|
||||
FormattedStringPart::Const(x) => x,
|
||||
FormattedStringPart::Container => "{}",
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join("")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,8 +14,6 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use leo_grammar::common::Declare as GrammarDeclare;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
@ -25,15 +23,6 @@ pub enum Declare {
|
||||
Let,
|
||||
}
|
||||
|
||||
impl<'ast> From<GrammarDeclare> for Declare {
|
||||
fn from(declare: GrammarDeclare) -> Self {
|
||||
match declare {
|
||||
GrammarDeclare::Const(_) => Declare::Const,
|
||||
GrammarDeclare::Let(_) => Declare::Let,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Declare {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user