mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-10-12 06:08:57 +03:00
Merge branch 'master' into leo-manifest-dependencies
This commit is contained in:
commit
6a2ebfc22e
0
FORMAT_ABNF_GRAMMER.md
Normal file
0
FORMAT_ABNF_GRAMMER.md
Normal file
@ -92,7 +92,7 @@ impl<'a> MonoidalReducerStatement<'a, BoolAnd> for ReturnPathReducer {
|
||||
if_true.append(if_false.unwrap_or(BoolAnd(false)))
|
||||
}
|
||||
|
||||
fn reduce_formatted_string(&mut self, input: &FormatString, parameters: Vec<BoolAnd>) -> BoolAnd {
|
||||
fn reduce_formatted_string(&mut self, input: &ConsoleArgs, parameters: Vec<BoolAnd>) -> BoolAnd {
|
||||
BoolAnd(false)
|
||||
}
|
||||
|
||||
|
@ -109,13 +109,29 @@ pub enum CharValue {
|
||||
NonScalar(u32),
|
||||
}
|
||||
|
||||
impl From<&leo_ast::Char> for CharValue {
|
||||
fn from(other: &leo_ast::Char) -> Self {
|
||||
use leo_ast::Char::*;
|
||||
match other {
|
||||
Scalar(value) => CharValue::Scalar(*value),
|
||||
NonScalar(value) => CharValue::NonScalar(*value),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<leo_ast::Char> for &CharValue {
|
||||
fn into(self) -> leo_ast::Char {
|
||||
use leo_ast::Char::*;
|
||||
match self {
|
||||
CharValue::Scalar(value) => Scalar(*value),
|
||||
CharValue::NonScalar(value) => NonScalar(*value),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<leo_ast::CharValue> for CharValue {
|
||||
fn from(other: leo_ast::CharValue) -> Self {
|
||||
use leo_ast::Char::*;
|
||||
match other.character {
|
||||
Scalar(value) => CharValue::Scalar(value),
|
||||
NonScalar(value) => CharValue::NonScalar(value),
|
||||
}
|
||||
Self::from(&other.character)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -148,24 +148,28 @@ impl<'a> FromAst<'a, leo_ast::ArrayRangeAccessExpression> for ArrayRangeAccessEx
|
||||
_ => None,
|
||||
};
|
||||
let const_right = match right.map(|x| x.const_value()) {
|
||||
Some(Some(ConstValue::Int(value))) => {
|
||||
let value = value.to_usize();
|
||||
if let Some(value) = value {
|
||||
if value > parent_size {
|
||||
return Err(AsgConvertError::array_index_out_of_bounds(
|
||||
value,
|
||||
&right.unwrap().span().cloned().unwrap_or_default(),
|
||||
));
|
||||
Some(Some(ConstValue::Int(inner_value))) => {
|
||||
let usize_value = inner_value.to_usize();
|
||||
if let Some(inner_value) = usize_value {
|
||||
if inner_value > parent_size {
|
||||
let error_span = if let Some(right) = right {
|
||||
right.span().cloned().unwrap_or_default()
|
||||
} else {
|
||||
value.span.clone()
|
||||
};
|
||||
return Err(AsgConvertError::array_index_out_of_bounds(inner_value, &error_span));
|
||||
} else if let Some(left) = const_left {
|
||||
if left > value {
|
||||
return Err(AsgConvertError::array_index_out_of_bounds(
|
||||
value,
|
||||
&right.unwrap().span().cloned().unwrap_or_default(),
|
||||
));
|
||||
if left > inner_value {
|
||||
let error_span = if let Some(right) = right {
|
||||
right.span().cloned().unwrap_or_default()
|
||||
} else {
|
||||
value.span.clone()
|
||||
};
|
||||
return Err(AsgConvertError::array_index_out_of_bounds(inner_value, &error_span));
|
||||
}
|
||||
}
|
||||
}
|
||||
value
|
||||
usize_value
|
||||
}
|
||||
None => Some(parent_size),
|
||||
_ => None,
|
||||
@ -188,12 +192,14 @@ impl<'a> FromAst<'a, leo_ast::ArrayRangeAccessExpression> for ArrayRangeAccessEx
|
||||
));
|
||||
}
|
||||
}
|
||||
if let Some(value) = const_left {
|
||||
if value + expected_len > parent_size {
|
||||
return Err(AsgConvertError::array_index_out_of_bounds(
|
||||
value,
|
||||
&left.unwrap().span().cloned().unwrap_or_default(),
|
||||
));
|
||||
if let Some(left_value) = const_left {
|
||||
if left_value + expected_len > parent_size {
|
||||
let error_span = if let Some(left) = left {
|
||||
left.span().cloned().unwrap_or_default()
|
||||
} else {
|
||||
value.span.clone()
|
||||
};
|
||||
return Err(AsgConvertError::array_index_out_of_bounds(left_value, &error_span));
|
||||
}
|
||||
}
|
||||
length = Some(expected_len);
|
||||
|
@ -225,7 +225,7 @@ impl<'a, T: Monoid, R: MonoidalReducerStatement<'a, T>> MonoidalDirector<'a, T,
|
||||
.reduce_conditional_statement(input, condition, if_true, if_false)
|
||||
}
|
||||
|
||||
pub fn reduce_formatted_string(&mut self, input: &FormatString<'a>) -> T {
|
||||
pub fn reduce_formatted_string(&mut self, input: &ConsoleArgs<'a>) -> T {
|
||||
let parameters = input
|
||||
.parameters
|
||||
.iter()
|
||||
|
@ -118,7 +118,7 @@ pub trait MonoidalReducerStatement<'a, T: Monoid>: MonoidalReducerExpression<'a,
|
||||
condition.append(if_true).append_option(if_false)
|
||||
}
|
||||
|
||||
fn reduce_formatted_string(&mut self, input: &FormatString<'a>, parameters: Vec<T>) -> T {
|
||||
fn reduce_formatted_string(&mut self, input: &ConsoleArgs<'a>, parameters: Vec<T>) -> T {
|
||||
T::default().append_all(parameters.into_iter())
|
||||
}
|
||||
|
||||
|
@ -243,7 +243,7 @@ impl<'a, R: ReconstructingReducerStatement<'a>> ReconstructingDirector<'a, R> {
|
||||
.reduce_conditional_statement(input, condition, if_true, if_false)
|
||||
}
|
||||
|
||||
pub fn reduce_formatted_string(&mut self, input: FormatString<'a>) -> FormatString<'a> {
|
||||
pub fn reduce_formatted_string(&mut self, input: ConsoleArgs<'a>) -> ConsoleArgs<'a> {
|
||||
let parameters = input
|
||||
.parameters
|
||||
.iter()
|
||||
|
@ -274,12 +274,12 @@ pub trait ReconstructingReducerStatement<'a>: ReconstructingReducerExpression<'a
|
||||
|
||||
fn reduce_formatted_string(
|
||||
&mut self,
|
||||
input: FormatString<'a>,
|
||||
input: ConsoleArgs<'a>,
|
||||
parameters: Vec<&'a Expression<'a>>,
|
||||
) -> FormatString<'a> {
|
||||
FormatString {
|
||||
) -> ConsoleArgs<'a> {
|
||||
ConsoleArgs {
|
||||
span: input.span,
|
||||
parts: input.parts,
|
||||
string: input.string,
|
||||
parameters: parameters.into_iter().map(Cell::new).collect(),
|
||||
}
|
||||
}
|
||||
@ -293,7 +293,7 @@ pub trait ReconstructingReducerStatement<'a>: ReconstructingReducerExpression<'a
|
||||
})
|
||||
}
|
||||
|
||||
fn reduce_console_log(&mut self, input: ConsoleStatement<'a>, argument: FormatString<'a>) -> Statement<'a> {
|
||||
fn reduce_console_log(&mut self, input: ConsoleStatement<'a>, argument: ConsoleArgs<'a>) -> Statement<'a> {
|
||||
assert!(!matches!(input.function, ConsoleFunction::Assert(_)));
|
||||
Statement::Console(ConsoleStatement {
|
||||
parent: input.parent,
|
||||
|
@ -120,7 +120,7 @@ pub trait StatementVisitor<'a>: ExpressionVisitor<'a> {
|
||||
Default::default()
|
||||
}
|
||||
|
||||
fn visit_formatted_string(&mut self, input: &FormatString<'a>) -> VisitResult {
|
||||
fn visit_formatted_string(&mut self, input: &ConsoleArgs<'a>) -> VisitResult {
|
||||
Default::default()
|
||||
}
|
||||
|
||||
|
@ -319,7 +319,7 @@ impl<'a, R: StatementVisitor<'a>> VisitorDirector<'a, R> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn visit_formatted_string(&mut self, input: &FormatString<'a>) -> ConcreteVisitResult {
|
||||
pub fn visit_formatted_string(&mut self, input: &ConsoleArgs<'a>) -> ConcreteVisitResult {
|
||||
match self.visitor.visit_formatted_string(input) {
|
||||
VisitResult::VisitChildren => {
|
||||
for parameter in input.parameters.iter() {
|
||||
|
@ -14,15 +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::{AsgConvertError, Expression, FromAst, Node, PartialType, Scope, Span, Statement, Type};
|
||||
use leo_ast::{ConsoleFunction as AstConsoleFunction, FormatStringPart};
|
||||
use crate::{AsgConvertError, CharValue, Expression, FromAst, Node, PartialType, Scope, Span, Statement, Type};
|
||||
use leo_ast::ConsoleFunction as AstConsoleFunction;
|
||||
|
||||
use std::cell::Cell;
|
||||
|
||||
// TODO (protryon): Refactor to not require/depend on span
|
||||
#[derive(Clone)]
|
||||
pub struct FormatString<'a> {
|
||||
pub parts: Vec<FormatStringPart>,
|
||||
pub struct ConsoleArgs<'a> {
|
||||
pub string: Vec<CharValue>,
|
||||
pub parameters: Vec<Cell<&'a Expression<'a>>>,
|
||||
pub span: Span,
|
||||
}
|
||||
@ -30,9 +30,9 @@ pub struct FormatString<'a> {
|
||||
#[derive(Clone)]
|
||||
pub enum ConsoleFunction<'a> {
|
||||
Assert(Cell<&'a Expression<'a>>),
|
||||
Debug(FormatString<'a>),
|
||||
Error(FormatString<'a>),
|
||||
Log(FormatString<'a>),
|
||||
Debug(ConsoleArgs<'a>),
|
||||
Error(ConsoleArgs<'a>),
|
||||
Log(ConsoleArgs<'a>),
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -48,41 +48,28 @@ impl<'a> Node for ConsoleStatement<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> FromAst<'a, leo_ast::FormatString> for FormatString<'a> {
|
||||
impl<'a> FromAst<'a, leo_ast::ConsoleArgs> for ConsoleArgs<'a> {
|
||||
fn from_ast(
|
||||
scope: &'a Scope<'a>,
|
||||
value: &leo_ast::FormatString,
|
||||
value: &leo_ast::ConsoleArgs,
|
||||
_expected_type: Option<PartialType<'a>>,
|
||||
) -> Result<Self, AsgConvertError> {
|
||||
let expected_param_len = value
|
||||
.parts
|
||||
.iter()
|
||||
.filter(|x| matches!(x, FormatStringPart::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(
|
||||
expected_param_len + 1,
|
||||
value.parameters.len() + 1,
|
||||
&value.span,
|
||||
));
|
||||
}
|
||||
let mut parameters = vec![];
|
||||
for parameter in value.parameters.iter() {
|
||||
parameters.push(Cell::new(<&Expression<'a>>::from_ast(scope, parameter, None)?));
|
||||
}
|
||||
Ok(FormatString {
|
||||
parts: value.parts.clone(),
|
||||
Ok(ConsoleArgs {
|
||||
string: value.string.iter().map(CharValue::from).collect::<Vec<_>>(),
|
||||
parameters,
|
||||
span: value.span.clone(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Into<leo_ast::FormatString> for &FormatString<'a> {
|
||||
fn into(self) -> leo_ast::FormatString {
|
||||
leo_ast::FormatString {
|
||||
parts: self.parts.clone(),
|
||||
impl<'a> Into<leo_ast::ConsoleArgs> for &ConsoleArgs<'a> {
|
||||
fn into(self) -> leo_ast::ConsoleArgs {
|
||||
leo_ast::ConsoleArgs {
|
||||
string: self.string.iter().map(|c| c.into()).collect::<Vec<_>>(),
|
||||
parameters: self.parameters.iter().map(|e| e.get().into()).collect(),
|
||||
span: self.span.clone(),
|
||||
}
|
||||
@ -102,15 +89,9 @@ impl<'a> FromAst<'a, leo_ast::ConsoleStatement> for ConsoleStatement<'a> {
|
||||
AstConsoleFunction::Assert(expression) => ConsoleFunction::Assert(Cell::new(
|
||||
<&Expression<'a>>::from_ast(scope, expression, Some(Type::Boolean.into()))?,
|
||||
)),
|
||||
AstConsoleFunction::Debug(formatted_string) => {
|
||||
ConsoleFunction::Debug(FormatString::from_ast(scope, formatted_string, None)?)
|
||||
}
|
||||
AstConsoleFunction::Error(formatted_string) => {
|
||||
ConsoleFunction::Error(FormatString::from_ast(scope, formatted_string, None)?)
|
||||
}
|
||||
AstConsoleFunction::Log(formatted_string) => {
|
||||
ConsoleFunction::Log(FormatString::from_ast(scope, formatted_string, None)?)
|
||||
}
|
||||
AstConsoleFunction::Debug(args) => ConsoleFunction::Debug(ConsoleArgs::from_ast(scope, args, None)?),
|
||||
AstConsoleFunction::Error(args) => ConsoleFunction::Error(ConsoleArgs::from_ast(scope, args, None)?),
|
||||
AstConsoleFunction::Log(args) => ConsoleFunction::Log(ConsoleArgs::from_ast(scope, args, None)?),
|
||||
},
|
||||
})
|
||||
}
|
||||
@ -122,9 +103,9 @@ impl<'a> Into<leo_ast::ConsoleStatement> for &ConsoleStatement<'a> {
|
||||
leo_ast::ConsoleStatement {
|
||||
function: match &self.function {
|
||||
Assert(e) => AstConsoleFunction::Assert(e.get().into()),
|
||||
Debug(formatted_string) => AstConsoleFunction::Debug(formatted_string.into()),
|
||||
Error(formatted_string) => AstConsoleFunction::Error(formatted_string.into()),
|
||||
Log(formatted_string) => AstConsoleFunction::Log(formatted_string.into()),
|
||||
Debug(args) => AstConsoleFunction::Debug(args.into()),
|
||||
Error(args) => AstConsoleFunction::Error(args.into()),
|
||||
Log(args) => AstConsoleFunction::Log(args.into()),
|
||||
},
|
||||
span: self.span.clone().unwrap_or_default(),
|
||||
}
|
||||
|
@ -1,3 +0,0 @@
|
||||
function main() {
|
||||
console.log("{}");
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
function main() {
|
||||
console.log("", 1u32);
|
||||
}
|
@ -27,15 +27,3 @@ fn test_log_parameter_fail_unknown() {
|
||||
let program_string = include_str!("log_parameter_fail_unknown.leo");
|
||||
load_asg(program_string).err().unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_log_parameter_fail_empty() {
|
||||
let program_string = include_str!("log_parameter_fail_empty.leo");
|
||||
load_asg(program_string).err().unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_log_parameter_fail_none() {
|
||||
let program_string = include_str!("log_parameter_fail_empty.leo");
|
||||
load_asg(program_string).err().unwrap();
|
||||
}
|
||||
|
340
ast/README.md
340
ast/README.md
@ -1,5 +1,343 @@
|
||||
# leo-ast
|
||||
|
||||
[![Crates.io](https://img.shields.io/crates/v/leo-ast.svg?color=neon)](https://crates.io/crates/leo-ast)
|
||||
[![Authors](https://img.shields.io/badge/authors-Aleo-orange.svg)](../AUTHORS)
|
||||
[![License](https://img.shields.io/badge/License-GPLv3-blue.svg)](./LICENSE.md)
|
||||
|
||||
This directory contains the code for the AST of a Leo Program.
|
||||
|
||||
## Node Types
|
||||
|
||||
There are several types of nodes in the AST that then have further breakdowns.
|
||||
|
||||
All nodes store a Span, which is useful for tracking the lines and
|
||||
columns of where the node was taken from in the Leo Program.
|
||||
|
||||
### [Program/File](./src/program.rs)
|
||||
|
||||
The top level nodes in a Leo Program.
|
||||
|
||||
#### [Imports](./src/imports/import.rs)
|
||||
|
||||
Represents an import statement in a Leo Program.
|
||||
A list of these are stored on the Program.
|
||||
It stores the path to an import and what is being imported.
|
||||
|
||||
**NOTE**: The import does not contain the source code of the imported Leo Program.
|
||||
|
||||
#### [Circuits](./src/circuits/circuit.rs)
|
||||
|
||||
A circuit node represents a defined Circuit in a Leo Program.
|
||||
A order preserving map of these are stored on the Program.
|
||||
Contains the Circuit's name, as well as it's members.
|
||||
The members are a function, or a variable.
|
||||
For both of them the Circuit preserves their names.
|
||||
|
||||
#### [Decorators](./src/annotation.rs)
|
||||
|
||||
An annotation node is a decorator that can be applied to a function.
|
||||
Stored on the function themselves despite being a top-level node.
|
||||
The node stores the name of the annotation, as well as any args passed to it.
|
||||
|
||||
#### [Functions](./src/functions/function.rs)
|
||||
|
||||
A function node represents a defined function in a Leo Program.
|
||||
A order preserving map of these are stored on the Program.
|
||||
A function node stores the following information:
|
||||
|
||||
- The annotations applied to the function.
|
||||
- An identifier the name of the function.
|
||||
- The inputs to the function, both their names and types.
|
||||
- The output of the function as a type if it exists.
|
||||
- The function body stored as a block statement.
|
||||
|
||||
#### [Global Consts](./src/program.rs)
|
||||
|
||||
A global const is a bit special and has no special node for itself, but rather is a definition statement.
|
||||
A order preserving map of these are stored on the Program.
|
||||
|
||||
### [Types](./src/types/type_.rs)
|
||||
|
||||
The different types in a Leo Program.
|
||||
Types themselves are not a node, but rather just information to be stored on a node.
|
||||
|
||||
#### Address
|
||||
|
||||
The address type follows the [BIP_0173](https://en.bitcoin.it/wiki/BIP_0173) format starting with `aleo1`.
|
||||
|
||||
#### Boolean
|
||||
|
||||
The boolean type consists of two values **true** and **false**.
|
||||
|
||||
#### Char
|
||||
|
||||
The char type resents a character from the inclusive range [0, 10FFFF].
|
||||
|
||||
#### Field
|
||||
|
||||
The field type an unsigned number up to the modulus length of the field.
|
||||
|
||||
#### Group
|
||||
|
||||
The group type a set of affine points on the elliptic curve passed.
|
||||
|
||||
#### [IntegerType](./src/types/integer_type.rs)
|
||||
|
||||
The integer type represents a range of integer types.
|
||||
|
||||
##### U8
|
||||
|
||||
A integer in the inclusive range [0, 255].
|
||||
|
||||
##### U16
|
||||
|
||||
A integer in the inclusive range [0, 65535].
|
||||
|
||||
##### U32
|
||||
|
||||
A integer in the inclusive range [0, 4294967295].
|
||||
|
||||
##### U64
|
||||
|
||||
A integer in the inclusive range [0, 18446744073709551615].
|
||||
|
||||
##### U128
|
||||
|
||||
A integer in the inclusive range [0, 340282366920938463463374607431768211455].
|
||||
|
||||
##### I8
|
||||
|
||||
A integer in the inclusive range [-128, 127].
|
||||
|
||||
##### I16
|
||||
|
||||
A integer in the inclusive range [-32768, 32767].
|
||||
|
||||
##### I32
|
||||
|
||||
A integer in the inclusive range [-2147483648, 2147483647].
|
||||
|
||||
##### I64
|
||||
|
||||
A integer in the inclusive range [-9223372036854775808, 9223372036854775807].
|
||||
|
||||
##### I128
|
||||
|
||||
A integer in the inclusive range [-170141183460469231731687303715884105728, 170141183460469231731687303715884105727].
|
||||
|
||||
#### Array
|
||||
|
||||
The array type contains another type, then the number of elements of that type greater than 0.
|
||||
|
||||
#### Tuple
|
||||
|
||||
The tuple type contains n types, where n is greater than or equal to 0.
|
||||
|
||||
#### Circuit
|
||||
|
||||
The circuit type, every circuit represents a different type.
|
||||
|
||||
#### SelfType
|
||||
|
||||
The self type represented by `Self` and only usable inside a circuit.
|
||||
|
||||
### [Statements](./src/statements/statement.rs)
|
||||
|
||||
The statement level nodes in a Leo Program.
|
||||
|
||||
#### [Assignment Statements](./src/statements/assign/)
|
||||
|
||||
An assignment statement node stores the following:
|
||||
|
||||
- The operation.
|
||||
- **=**
|
||||
- **+=**
|
||||
- **-=**
|
||||
- **=**
|
||||
- **/=**
|
||||
- **=**
|
||||
- **&&=**
|
||||
- **||=**
|
||||
- The assignee which is a variable that has context of any access expressions on it.
|
||||
- The value which is an expression.
|
||||
|
||||
#### [Block Statements](./src/statements/block.rs)
|
||||
|
||||
A block statement node stores the following:
|
||||
|
||||
- The list of statements inside the block.
|
||||
|
||||
#### [Conditional Statements](./src/statements/conditional.rs)
|
||||
|
||||
A conditional statement node stores the following:
|
||||
|
||||
- The condition which is an expression.
|
||||
- The block statement.
|
||||
- The next block of the conditional if it exists.
|
||||
|
||||
#### [Console Statements](./src/statements/)
|
||||
|
||||
A console statement node stores the following:
|
||||
|
||||
- The console function being called which stores the type of console function it is and its arguments.
|
||||
|
||||
#### [Definition Statements](./src/statements/definition/mod.rs)
|
||||
|
||||
A definition statement node stores the following:
|
||||
|
||||
- The declaration type:
|
||||
- `let` for mutable definitions.
|
||||
- `const` for cosntant definitions.
|
||||
- The names of the varaibles defined.
|
||||
- The optional type.
|
||||
- The values to be assigned to the varaibles.
|
||||
|
||||
#### [Expression Statements](./src/statements/expression.rs)
|
||||
|
||||
An expression statement node stores the following:
|
||||
|
||||
- The expression.
|
||||
|
||||
#### [Iteration Statements](./src/statements/iteration.rs)
|
||||
|
||||
A iteration statement node stores the following:
|
||||
|
||||
- The loop iterator variable name.
|
||||
- The expression to define the starting loop value.
|
||||
- The expression to define the stoping loop value.
|
||||
- The block to run for the loop.
|
||||
|
||||
#### [Return Statements](./src/statements/return_statement.rs)
|
||||
|
||||
A return statement node stores the following:
|
||||
|
||||
- The expression that is being returned.
|
||||
|
||||
### Expressions
|
||||
|
||||
The expression nodes in a Leo Program.
|
||||
|
||||
#### [ArrayAccess Expressions](./src/expression/array_acces.rs)
|
||||
|
||||
An array access expression node stores the following:
|
||||
|
||||
- The array expression.
|
||||
- The index represented by an expression.
|
||||
|
||||
#### [ArrayInit Expressions](./src/expression/array_init.rs)
|
||||
|
||||
An array init expression node stores the following:
|
||||
|
||||
- The element expression to fill the array with.
|
||||
- The dimensions of the array to build.
|
||||
|
||||
#### [ArrayInline Expressions](./src/expression/array_inline.rs)
|
||||
|
||||
An array inline expression node stores the following:
|
||||
|
||||
- The elments of an array which is either an spread or an expression.
|
||||
|
||||
#### [ArrayRangeAccess Expressions](./src/expression/array_range_access.rs)
|
||||
|
||||
An array range access expression node stores the following:
|
||||
|
||||
- The array expression.
|
||||
- The optional left side of the range of the array bounds to access.
|
||||
- The optional right side of the range of the array bounds to access.
|
||||
|
||||
#### [Binary Expressions](./src/expression/binary.rs)
|
||||
|
||||
A binary expression node stores the following:
|
||||
|
||||
- The left side of the expression.
|
||||
- The right side of the expression.
|
||||
- The binary operation of the expression:
|
||||
- **+**
|
||||
- **-**
|
||||
- **\***
|
||||
- **/**
|
||||
- **\*\***
|
||||
- **||**
|
||||
- **&&**
|
||||
- **==**
|
||||
- **!=**
|
||||
- **>=**
|
||||
- **>**
|
||||
- **<=**
|
||||
- **<**
|
||||
|
||||
#### [Call Expressions](./src/expression/call.rs)
|
||||
|
||||
A call expression node stores the following:
|
||||
|
||||
- The function expression being called.
|
||||
- The aruments a list of expressions.
|
||||
|
||||
#### [CircuitInit Expressions](./src/expression/circuit_init.rs)
|
||||
|
||||
A circuit init expression node stores the following:
|
||||
|
||||
- The name of the circuit expression being initialized.
|
||||
- The aruments a list of expressions.
|
||||
|
||||
#### [CircuitMemberAccess Expressions](./src/expression/circuit_member_access.rs)
|
||||
|
||||
A circuit member access expression node stores the following:
|
||||
|
||||
- The circut expression being accessed.
|
||||
- The name of the expression being accessed from the circuit.
|
||||
|
||||
#### [CircuitStaticFunctionAccess Expressions](./src/expression/circuit_static_function_access.rs)
|
||||
|
||||
A circuit static function access expression node stores the following:
|
||||
|
||||
- The circut expression being accessed.
|
||||
- The name of the expression being statically accessed from the circuit.
|
||||
|
||||
#### [Identifier Expressions](./src/common/identifier.rs)
|
||||
|
||||
An identifer expression node stores the following:
|
||||
|
||||
- An identifier stores the string name.
|
||||
|
||||
#### [Ternary Expressions](./src/expression/ternary.rs)
|
||||
|
||||
A ternary expression node stores the following:
|
||||
|
||||
- The condition of the ternary stored as an expression.
|
||||
- The expression returned if the condition is true.
|
||||
- The expression returned if the condition is false.
|
||||
|
||||
#### [TupleAccess Expressions](./src/expression/tuple_access.rs)
|
||||
|
||||
A tuple access expression node stores the following:
|
||||
|
||||
- The tuple expression being accessed.
|
||||
- The index a positive number greater than or equal to 0.
|
||||
|
||||
#### [TupleInit Expressions](./src/expression/tuple_init.rs)
|
||||
|
||||
A tuple init expression node stores the following:
|
||||
|
||||
- The element expressions to fill the tuple with.
|
||||
|
||||
#### [Unary Expressions](./src/expression/unary.rs)
|
||||
|
||||
An unary expression node stores the following:
|
||||
|
||||
- The inner expression.
|
||||
- The unary operator:
|
||||
- **!**
|
||||
- **-**
|
||||
|
||||
#### [Value Expressions](./src/expression/value.rs)
|
||||
|
||||
A value expression node stores one of the following:
|
||||
|
||||
- Address and its value and span.
|
||||
- Boolean and its value and span.
|
||||
- Char and its value and span.
|
||||
- Field and its value and span.
|
||||
- Group and its value and span.
|
||||
- Implicit and its value and span.
|
||||
- Integer and its value and span.
|
||||
- String and its value and span.
|
||||
|
@ -35,6 +35,13 @@ impl ReducerError {
|
||||
ReducerError::Error(FormattedError::new_from_span(message, span))
|
||||
}
|
||||
|
||||
pub fn empty_string(span: &Span) -> Self {
|
||||
let message =
|
||||
"Cannot constrcut an empty string: it has the type of [char; 0] which is not possible.".to_string();
|
||||
|
||||
Self::new_from_span(message, span)
|
||||
}
|
||||
|
||||
pub fn impossible_console_assert_call(span: &Span) -> Self {
|
||||
let message = "Console::Assert cannot be matched here, its handled in another case.".to_string();
|
||||
|
||||
|
@ -118,6 +118,11 @@ impl Ast {
|
||||
let ast: Program = serde_json::from_str(json)?;
|
||||
Ok(Self { ast })
|
||||
}
|
||||
|
||||
pub fn from_json_file(path: std::path::PathBuf) -> Result<Self, AstError> {
|
||||
let data = std::fs::read_to_string(path)?;
|
||||
Self::from_json_string(&data)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<Program> for Ast {
|
||||
|
@ -391,23 +391,23 @@ impl Canonicalizer {
|
||||
ConsoleFunction::Assert(expression) => {
|
||||
ConsoleFunction::Assert(self.canonicalize_expression(expression))
|
||||
}
|
||||
ConsoleFunction::Debug(format) | ConsoleFunction::Error(format) | ConsoleFunction::Log(format) => {
|
||||
let parameters = format
|
||||
ConsoleFunction::Debug(args) | ConsoleFunction::Error(args) | ConsoleFunction::Log(args) => {
|
||||
let parameters = args
|
||||
.parameters
|
||||
.iter()
|
||||
.map(|parameter| self.canonicalize_expression(parameter))
|
||||
.collect();
|
||||
|
||||
let formatted = FormatString {
|
||||
parts: format.parts.clone(),
|
||||
let console_args = ConsoleArgs {
|
||||
string: args.string.clone(),
|
||||
parameters,
|
||||
span: format.span.clone(),
|
||||
span: args.span.clone(),
|
||||
};
|
||||
|
||||
match &console_function_call.function {
|
||||
ConsoleFunction::Debug(_) => ConsoleFunction::Debug(formatted),
|
||||
ConsoleFunction::Error(_) => ConsoleFunction::Error(formatted),
|
||||
ConsoleFunction::Log(_) => ConsoleFunction::Log(formatted),
|
||||
ConsoleFunction::Debug(_) => ConsoleFunction::Debug(console_args),
|
||||
ConsoleFunction::Error(_) => ConsoleFunction::Error(console_args),
|
||||
ConsoleFunction::Log(_) => ConsoleFunction::Log(console_args),
|
||||
_ => unimplemented!(), // impossible
|
||||
}
|
||||
}
|
||||
@ -493,6 +493,10 @@ impl ReconstructingReducer for Canonicalizer {
|
||||
}
|
||||
|
||||
fn reduce_string(&mut self, string: &[Char], span: &Span) -> Result<Expression, ReducerError> {
|
||||
if string.is_empty() {
|
||||
return Err(ReducerError::empty_string(span));
|
||||
}
|
||||
|
||||
let mut elements = Vec::new();
|
||||
let mut col_adder = 0;
|
||||
for (index, character) in string.iter().enumerate() {
|
||||
|
@ -390,23 +390,23 @@ impl<R: ReconstructingReducer> ReconstructingDirector<R> {
|
||||
) -> Result<ConsoleStatement, ReducerError> {
|
||||
let function = match &console_function_call.function {
|
||||
ConsoleFunction::Assert(expression) => ConsoleFunction::Assert(self.reduce_expression(expression)?),
|
||||
ConsoleFunction::Debug(format) | ConsoleFunction::Error(format) | ConsoleFunction::Log(format) => {
|
||||
ConsoleFunction::Debug(args) | ConsoleFunction::Error(args) | ConsoleFunction::Log(args) => {
|
||||
let mut parameters = vec![];
|
||||
for parameter in format.parameters.iter() {
|
||||
for parameter in args.parameters.iter() {
|
||||
parameters.push(self.reduce_expression(parameter)?);
|
||||
}
|
||||
|
||||
let formatted = FormatString {
|
||||
parts: format.parts.clone(),
|
||||
let formatted = ConsoleArgs {
|
||||
string: args.string.clone(),
|
||||
parameters,
|
||||
span: format.span.clone(),
|
||||
span: args.span.clone(),
|
||||
};
|
||||
|
||||
match &console_function_call.function {
|
||||
ConsoleFunction::Debug(_) => ConsoleFunction::Debug(formatted),
|
||||
ConsoleFunction::Error(_) => ConsoleFunction::Error(formatted),
|
||||
ConsoleFunction::Log(_) => ConsoleFunction::Log(formatted),
|
||||
_ => return Err(ReducerError::impossible_console_assert_call(&format.span)),
|
||||
_ => return Err(ReducerError::impossible_console_assert_call(&args.span)),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -14,23 +14,34 @@
|
||||
// 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::{Node, Span};
|
||||
use crate::{Char, Expression, Node, Span};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
|
||||
pub struct FormattedContainer {
|
||||
pub struct ConsoleArgs {
|
||||
pub string: Vec<Char>,
|
||||
pub parameters: Vec<Expression>,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
impl fmt::Display for FormattedContainer {
|
||||
impl fmt::Display for ConsoleArgs {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{{}}")
|
||||
write!(
|
||||
f,
|
||||
"\"{}\", {}",
|
||||
self.string.iter().map(|x| x.to_string()).collect::<Vec<_>>().join(""),
|
||||
self.parameters
|
||||
.iter()
|
||||
.map(|p| p.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join(",")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Node for FormattedContainer {
|
||||
impl Node for ConsoleArgs {
|
||||
fn span(&self) -> &Span {
|
||||
&self.span
|
||||
}
|
@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::{Expression, FormatString, Node, Span};
|
||||
use crate::{ConsoleArgs, Expression, Node, Span};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
@ -22,9 +22,9 @@ use std::fmt;
|
||||
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
|
||||
pub enum ConsoleFunction {
|
||||
Assert(Expression),
|
||||
Debug(FormatString),
|
||||
Error(FormatString),
|
||||
Log(FormatString),
|
||||
Debug(ConsoleArgs),
|
||||
Error(ConsoleArgs),
|
||||
Log(ConsoleArgs),
|
||||
}
|
||||
|
||||
impl fmt::Display for ConsoleFunction {
|
||||
|
@ -1,103 +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::{Char, Expression, Node, Span};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
use tendril::StrTendril;
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
|
||||
pub enum FormatStringPart {
|
||||
Const(#[serde(with = "crate::common::tendril_json")] StrTendril),
|
||||
Container,
|
||||
}
|
||||
|
||||
impl FormatStringPart {
|
||||
pub fn from_string(string: Vec<Char>) -> Vec<Self> {
|
||||
let mut parts = Vec::new();
|
||||
let mut in_container = false;
|
||||
let mut substring = String::new();
|
||||
for (_, character) in string.iter().enumerate() {
|
||||
match character {
|
||||
Char::Scalar(scalar) => match scalar {
|
||||
'{' if !in_container => {
|
||||
parts.push(FormatStringPart::Const(substring.clone().into()));
|
||||
substring.clear();
|
||||
in_container = true;
|
||||
}
|
||||
'}' if in_container => {
|
||||
in_container = false;
|
||||
parts.push(FormatStringPart::Container);
|
||||
}
|
||||
_ if in_container => {
|
||||
in_container = false;
|
||||
}
|
||||
_ => substring.push(*scalar),
|
||||
},
|
||||
Char::NonScalar(non_scalar) => {
|
||||
substring.push_str(format!("\\u{{{:x}}}", non_scalar).as_str());
|
||||
in_container = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !substring.is_empty() {
|
||||
parts.push(FormatStringPart::Const(substring.into()));
|
||||
}
|
||||
|
||||
parts
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
|
||||
pub struct FormatString {
|
||||
pub parts: Vec<FormatStringPart>,
|
||||
pub parameters: Vec<Expression>,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
impl fmt::Display for FormatString {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"\"{}\", {}",
|
||||
self.parts
|
||||
.iter()
|
||||
.map(|x| match x {
|
||||
FormatStringPart::Const(x) => x.to_string(),
|
||||
FormatStringPart::Container => "{}".to_string(),
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join(""),
|
||||
self.parameters
|
||||
.iter()
|
||||
.map(|p| p.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join(",")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Node for FormatString {
|
||||
fn span(&self) -> &Span {
|
||||
&self.span
|
||||
}
|
||||
|
||||
fn set_span(&mut self, span: Span) {
|
||||
self.span = span;
|
||||
}
|
||||
}
|
@ -17,11 +17,8 @@
|
||||
pub mod console_function;
|
||||
pub use console_function::*;
|
||||
|
||||
pub mod console_args;
|
||||
pub use console_args::*;
|
||||
|
||||
pub mod console_statement;
|
||||
pub use console_statement::*;
|
||||
|
||||
pub mod formatted_container;
|
||||
pub use formatted_container::*;
|
||||
|
||||
pub mod formatted_string;
|
||||
pub use formatted_string::*;
|
||||
|
@ -18,11 +18,11 @@
|
||||
use crate::{
|
||||
constraints::{generate_constraints, generate_test_constraints},
|
||||
errors::CompilerError,
|
||||
AstSnapshotOptions,
|
||||
CompilerOptions,
|
||||
GroupType,
|
||||
Output,
|
||||
OutputFile,
|
||||
TheoremOptions,
|
||||
TypeInferencePhase,
|
||||
};
|
||||
pub use leo_asg::{new_context, AsgContext as Context, AsgContext};
|
||||
@ -69,8 +69,8 @@ pub struct Compiler<'a, F: PrimeField, G: GroupType<F>> {
|
||||
context: AsgContext<'a>,
|
||||
asg: Option<AsgProgram<'a>>,
|
||||
options: CompilerOptions,
|
||||
proof_options: TheoremOptions,
|
||||
imports_map: HashMap<String, String>,
|
||||
ast_snapshot_options: AstSnapshotOptions,
|
||||
_engine: PhantomData<F>,
|
||||
_group: PhantomData<G>,
|
||||
}
|
||||
@ -85,8 +85,8 @@ impl<'a, F: PrimeField, G: GroupType<F>> Compiler<'a, F, G> {
|
||||
output_directory: PathBuf,
|
||||
context: AsgContext<'a>,
|
||||
options: Option<CompilerOptions>,
|
||||
proof_options: Option<TheoremOptions>,
|
||||
imports_map: HashMap<String, String>,
|
||||
ast_snapshot_options: Option<AstSnapshotOptions>,
|
||||
) -> Self {
|
||||
Self {
|
||||
program_name: package_name.clone(),
|
||||
@ -97,8 +97,8 @@ impl<'a, F: PrimeField, G: GroupType<F>> Compiler<'a, F, G> {
|
||||
asg: None,
|
||||
context,
|
||||
options: options.unwrap_or_default(),
|
||||
proof_options: proof_options.unwrap_or_default(),
|
||||
imports_map,
|
||||
ast_snapshot_options: ast_snapshot_options.unwrap_or_default(),
|
||||
_engine: PhantomData,
|
||||
_group: PhantomData,
|
||||
}
|
||||
@ -117,8 +117,8 @@ impl<'a, F: PrimeField, G: GroupType<F>> Compiler<'a, F, G> {
|
||||
output_directory: PathBuf,
|
||||
context: AsgContext<'a>,
|
||||
options: Option<CompilerOptions>,
|
||||
proof_options: Option<TheoremOptions>,
|
||||
imports_map: HashMap<String, String>,
|
||||
ast_snapshot_options: Option<AstSnapshotOptions>,
|
||||
) -> Result<Self, CompilerError> {
|
||||
let mut compiler = Self::new(
|
||||
package_name,
|
||||
@ -126,8 +126,8 @@ impl<'a, F: PrimeField, G: GroupType<F>> Compiler<'a, F, G> {
|
||||
output_directory,
|
||||
context,
|
||||
options,
|
||||
proof_options,
|
||||
imports_map,
|
||||
ast_snapshot_options,
|
||||
);
|
||||
|
||||
compiler.parse_program()?;
|
||||
@ -158,8 +158,8 @@ impl<'a, F: PrimeField, G: GroupType<F>> Compiler<'a, F, G> {
|
||||
state_path: &Path,
|
||||
context: AsgContext<'a>,
|
||||
options: Option<CompilerOptions>,
|
||||
proof_options: Option<TheoremOptions>,
|
||||
imports_map: HashMap<String, String>,
|
||||
ast_snapshot_options: Option<AstSnapshotOptions>,
|
||||
) -> Result<Self, CompilerError> {
|
||||
let mut compiler = Self::new(
|
||||
package_name,
|
||||
@ -167,8 +167,8 @@ impl<'a, F: PrimeField, G: GroupType<F>> Compiler<'a, F, G> {
|
||||
output_directory,
|
||||
context,
|
||||
options,
|
||||
proof_options,
|
||||
imports_map,
|
||||
ast_snapshot_options,
|
||||
);
|
||||
|
||||
compiler.parse_input(input_string, input_path, state_string, state_path)?;
|
||||
@ -249,7 +249,7 @@ impl<'a, F: PrimeField, G: GroupType<F>> Compiler<'a, F, G> {
|
||||
|
||||
let mut ast: leo_ast::Ast = parse_ast(self.main_file_path.to_str().unwrap_or_default(), program_string)?;
|
||||
|
||||
if self.proof_options.initial {
|
||||
if self.ast_snapshot_options.initial {
|
||||
ast.to_json_file(self.output_directory.clone(), "initial_ast.json")?;
|
||||
}
|
||||
|
||||
@ -257,7 +257,7 @@ impl<'a, F: PrimeField, G: GroupType<F>> Compiler<'a, F, G> {
|
||||
if self.options.canonicalization_enabled {
|
||||
ast.canonicalize()?;
|
||||
|
||||
if self.proof_options.canonicalized {
|
||||
if self.ast_snapshot_options.canonicalized {
|
||||
ast.to_json_file(self.output_directory.clone(), "canonicalization_ast.json")?;
|
||||
}
|
||||
}
|
||||
@ -275,7 +275,7 @@ impl<'a, F: PrimeField, G: GroupType<F>> Compiler<'a, F, G> {
|
||||
&mut ImportParser::new(self.main_file_path.clone(), self.imports_map.clone()),
|
||||
)?;
|
||||
|
||||
if self.proof_options.type_inferenced {
|
||||
if self.ast_snapshot_options.type_inferenced {
|
||||
let new_ast = TypeInferencePhase::default()
|
||||
.phase_ast(&self.program, &asg.clone().into_repr())
|
||||
.expect("Failed to produce type inference ast.");
|
||||
|
@ -17,8 +17,7 @@
|
||||
//! Evaluates a formatted string in a compiled Leo program.
|
||||
|
||||
use crate::{errors::ConsoleError, program::ConstrainedProgram, GroupType};
|
||||
use leo_asg::FormatString;
|
||||
use leo_ast::FormatStringPart;
|
||||
use leo_asg::{CharValue, ConsoleArgs};
|
||||
use snarkvm_fields::PrimeField;
|
||||
use snarkvm_r1cs::ConstraintSystem;
|
||||
|
||||
@ -26,35 +25,65 @@ impl<'a, F: PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
|
||||
pub fn format<CS: ConstraintSystem<F>>(
|
||||
&mut self,
|
||||
cs: &mut CS,
|
||||
formatted: &FormatString<'a>,
|
||||
args: &ConsoleArgs<'a>,
|
||||
) -> Result<String, ConsoleError> {
|
||||
// Check that containers and parameters match
|
||||
let container_count = formatted
|
||||
.parts
|
||||
.iter()
|
||||
.filter(|x| matches!(x, FormatStringPart::Container))
|
||||
.count();
|
||||
if container_count != formatted.parameters.len() {
|
||||
return Err(ConsoleError::length(
|
||||
container_count,
|
||||
formatted.parameters.len(),
|
||||
&formatted.span,
|
||||
));
|
||||
}
|
||||
|
||||
let mut executed_containers = Vec::with_capacity(formatted.parameters.len());
|
||||
for parameter in formatted.parameters.iter() {
|
||||
executed_containers.push(self.enforce_expression(cs, parameter.get())?.to_string());
|
||||
}
|
||||
|
||||
let mut out = vec![];
|
||||
let mut parameters = executed_containers.iter();
|
||||
for part in formatted.parts.iter() {
|
||||
match part {
|
||||
FormatStringPart::Const(c) => out.push(c.to_string()),
|
||||
FormatStringPart::Container => out.push(parameters.next().unwrap().to_string()),
|
||||
let mut out = Vec::new();
|
||||
let mut in_container = false;
|
||||
let mut substring = String::new();
|
||||
let mut arg_index = 0;
|
||||
let mut escape_right_bracket = false;
|
||||
for (index, character) in args.string.iter().enumerate() {
|
||||
match character {
|
||||
_ if escape_right_bracket => {
|
||||
escape_right_bracket = false;
|
||||
continue;
|
||||
}
|
||||
CharValue::Scalar(scalar) => match scalar {
|
||||
'{' if !in_container => {
|
||||
out.push(substring.clone());
|
||||
substring.clear();
|
||||
in_container = true;
|
||||
}
|
||||
'{' if in_container => {
|
||||
substring.push('{');
|
||||
in_container = false;
|
||||
}
|
||||
'}' if in_container => {
|
||||
in_container = false;
|
||||
let parameter = match args.parameters.get(arg_index) {
|
||||
Some(index) => index,
|
||||
None => return Err(ConsoleError::length(arg_index + 1, args.parameters.len(), &args.span)),
|
||||
};
|
||||
out.push(self.enforce_expression(cs, parameter.get())?.to_string());
|
||||
arg_index += 1;
|
||||
}
|
||||
'}' if !in_container => {
|
||||
if let Some(CharValue::Scalar(next)) = args.string.get(index + 1) {
|
||||
if *next == '}' {
|
||||
substring.push('}');
|
||||
escape_right_bracket = true;
|
||||
} else {
|
||||
return Err(ConsoleError::expected_escaped_right_brace(&args.span));
|
||||
}
|
||||
}
|
||||
}
|
||||
_ if in_container => {
|
||||
return Err(ConsoleError::expected_left_or_right_brace(&args.span));
|
||||
}
|
||||
_ => substring.push(*scalar),
|
||||
},
|
||||
CharValue::NonScalar(non_scalar) => {
|
||||
substring.push_str(format!("\\u{{{:x}}}", non_scalar).as_str());
|
||||
in_container = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
out.push(substring);
|
||||
|
||||
// Check that containers and parameters match
|
||||
if arg_index != args.parameters.len() {
|
||||
return Err(ConsoleError::length(arg_index, args.parameters.len(), &args.span));
|
||||
}
|
||||
|
||||
Ok(out.join(""))
|
||||
}
|
||||
|
@ -33,6 +33,18 @@ impl ConsoleError {
|
||||
ConsoleError::Error(FormattedError::new_from_span(message, span))
|
||||
}
|
||||
|
||||
pub fn expected_left_or_right_brace(span: &Span) -> Self {
|
||||
let message = "Formatter given a {. Expected a { or } after".to_string();
|
||||
|
||||
Self::new_from_span(message, span)
|
||||
}
|
||||
|
||||
pub fn expected_escaped_right_brace(span: &Span) -> Self {
|
||||
let message = "Formatter given a }. Expected a container {} or }}".to_string();
|
||||
|
||||
Self::new_from_span(message, span)
|
||||
}
|
||||
|
||||
pub fn length(containers: usize, parameters: usize, span: &Span) -> Self {
|
||||
let message = format!(
|
||||
"Formatter given {} containers and found {} parameters",
|
||||
|
@ -65,3 +65,6 @@ pub use phases::*;
|
||||
|
||||
pub mod option;
|
||||
pub use option::*;
|
||||
|
||||
#[cfg(test)]
|
||||
mod test;
|
||||
|
@ -38,13 +38,13 @@ impl Default for CompilerOptions {
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct TheoremOptions {
|
||||
pub struct AstSnapshotOptions {
|
||||
pub initial: bool,
|
||||
pub canonicalized: bool,
|
||||
pub type_inferenced: bool,
|
||||
}
|
||||
|
||||
impl Default for TheoremOptions {
|
||||
impl Default for AstSnapshotOptions {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
initial: false,
|
||||
|
@ -76,12 +76,12 @@ use leo_ast::{
|
||||
CircuitStaticFunctionAccessExpression,
|
||||
CombinerError,
|
||||
ConditionalStatement as AstConditionalStatement,
|
||||
ConsoleArgs as AstConsoleArgs,
|
||||
ConsoleFunction as AstConsoleFunction,
|
||||
ConsoleStatement as AstConsoleStatement,
|
||||
DefinitionStatement as AstDefinitionStatement,
|
||||
Expression as AstExpression,
|
||||
ExpressionStatement as AstExpressionStatement,
|
||||
FormatString,
|
||||
Function as AstFunction,
|
||||
GroupTuple,
|
||||
GroupValue as AstGroupValue,
|
||||
@ -597,25 +597,27 @@ impl<R: ReconstructingReducer, O: CombinerOptions> CombineAstAsgDirector<R, O> {
|
||||
(AstConsoleFunction::Assert(ast_expression), AsgConsoleFunction::Assert(asg_expression)) => {
|
||||
AstConsoleFunction::Assert(self.reduce_expression(&ast_expression, asg_expression.get())?)
|
||||
}
|
||||
(AstConsoleFunction::Debug(ast_format), AsgConsoleFunction::Debug(asg_format))
|
||||
| (AstConsoleFunction::Error(ast_format), AsgConsoleFunction::Error(asg_format))
|
||||
| (AstConsoleFunction::Log(ast_format), AsgConsoleFunction::Log(asg_format)) => {
|
||||
(AstConsoleFunction::Debug(ast_console_args), AsgConsoleFunction::Debug(asg_format))
|
||||
| (AstConsoleFunction::Error(ast_console_args), AsgConsoleFunction::Error(asg_format))
|
||||
| (AstConsoleFunction::Log(ast_console_args), AsgConsoleFunction::Log(asg_format)) => {
|
||||
let mut parameters = vec![];
|
||||
for (ast_parameter, asg_parameter) in ast_format.parameters.iter().zip(asg_format.parameters.iter()) {
|
||||
for (ast_parameter, asg_parameter) in
|
||||
ast_console_args.parameters.iter().zip(asg_format.parameters.iter())
|
||||
{
|
||||
parameters.push(self.reduce_expression(&ast_parameter, asg_parameter.get())?);
|
||||
}
|
||||
|
||||
let formatted = FormatString {
|
||||
parts: ast_format.parts.clone(),
|
||||
let args = AstConsoleArgs {
|
||||
string: ast_console_args.string.clone(),
|
||||
parameters,
|
||||
span: ast_format.span.clone(),
|
||||
span: ast_console_args.span.clone(),
|
||||
};
|
||||
|
||||
match &ast.function {
|
||||
AstConsoleFunction::Debug(_) => AstConsoleFunction::Debug(formatted),
|
||||
AstConsoleFunction::Error(_) => AstConsoleFunction::Error(formatted),
|
||||
AstConsoleFunction::Log(_) => AstConsoleFunction::Log(formatted),
|
||||
_ => return Err(ReducerError::impossible_console_assert_call(&ast_format.span)),
|
||||
AstConsoleFunction::Debug(_) => AstConsoleFunction::Debug(args),
|
||||
AstConsoleFunction::Error(_) => AstConsoleFunction::Error(args),
|
||||
AstConsoleFunction::Log(_) => AstConsoleFunction::Log(args),
|
||||
_ => return Err(ReducerError::impossible_console_assert_call(&ast_console_args.span)),
|
||||
}
|
||||
}
|
||||
_ => ast.function.clone(),
|
||||
|
@ -20,6 +20,7 @@ use std::{
|
||||
};
|
||||
|
||||
use leo_asg::*;
|
||||
use leo_ast::{Ast, Program};
|
||||
use leo_synthesizer::{CircuitSynthesizer, SerializedCircuit, SummarizedCircuit};
|
||||
use leo_test_framework::{
|
||||
runner::{Namespace, ParseType, Runner},
|
||||
@ -28,7 +29,13 @@ use leo_test_framework::{
|
||||
use serde_yaml::Value;
|
||||
use snarkvm_curves::{bls12_377::Bls12_377, edwards_bls12::Fq};
|
||||
|
||||
use leo_compiler::{compiler::Compiler, errors::CompilerError, targets::edwards_bls12::EdwardsGroupType, Output};
|
||||
use crate::{
|
||||
compiler::Compiler,
|
||||
errors::CompilerError,
|
||||
targets::edwards_bls12::EdwardsGroupType,
|
||||
AstSnapshotOptions,
|
||||
Output,
|
||||
};
|
||||
|
||||
pub type EdwardsTestCompiler = Compiler<'static, Fq, EdwardsGroupType>;
|
||||
// pub type EdwardsConstrainedValue = ConstrainedValue<'static, Fq, EdwardsGroupType>;
|
||||
@ -39,9 +46,10 @@ pub(crate) fn make_test_context() -> AsgContext<'static> {
|
||||
new_context(allocator)
|
||||
}
|
||||
|
||||
fn new_compiler(path: PathBuf) -> EdwardsTestCompiler {
|
||||
fn new_compiler(path: PathBuf, theorem_options: Option<AstSnapshotOptions>) -> EdwardsTestCompiler {
|
||||
let program_name = "test".to_string();
|
||||
let output_dir = PathBuf::from("/output/");
|
||||
let output_dir = PathBuf::from("/tmp/output/");
|
||||
std::fs::create_dir_all(output_dir.clone()).unwrap();
|
||||
|
||||
EdwardsTestCompiler::new(
|
||||
program_name,
|
||||
@ -49,13 +57,25 @@ fn new_compiler(path: PathBuf) -> EdwardsTestCompiler {
|
||||
output_dir,
|
||||
make_test_context(),
|
||||
None,
|
||||
None,
|
||||
HashMap::new(),
|
||||
theorem_options,
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn parse_program(program_string: &str) -> Result<EdwardsTestCompiler, CompilerError> {
|
||||
let mut compiler = new_compiler("compiler-test".into());
|
||||
fn hash(input: String) -> String {
|
||||
use sha2::{Digest, Sha256};
|
||||
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.update(input.as_bytes());
|
||||
let output = hasher.finalize();
|
||||
hex::encode(&output[..])
|
||||
}
|
||||
|
||||
pub(crate) fn parse_program(
|
||||
program_string: &str,
|
||||
theorem_options: Option<AstSnapshotOptions>,
|
||||
) -> Result<EdwardsTestCompiler, CompilerError> {
|
||||
let mut compiler = new_compiler("compiler-test".into(), theorem_options);
|
||||
|
||||
compiler.parse_program_from_string(program_string)?;
|
||||
|
||||
@ -74,6 +94,9 @@ struct OutputItem {
|
||||
struct CompileOutput {
|
||||
pub circuit: SummarizedCircuit,
|
||||
pub output: Vec<OutputItem>,
|
||||
pub initial_ast: String,
|
||||
pub canonicalized_ast: String,
|
||||
pub type_inferenced_ast: String,
|
||||
}
|
||||
|
||||
impl Namespace for CompileNamespace {
|
||||
@ -96,24 +119,30 @@ impl Namespace for CompileNamespace {
|
||||
// })
|
||||
// .unwrap_or(test.path.clone());
|
||||
|
||||
let parsed = parse_program(&test.content).map_err(|x| x.to_string())?;
|
||||
let parsed = parse_program(
|
||||
&test.content,
|
||||
Some(AstSnapshotOptions {
|
||||
initial: true,
|
||||
canonicalized: true,
|
||||
type_inferenced: true,
|
||||
}),
|
||||
)
|
||||
.map_err(|x| x.to_string())?;
|
||||
|
||||
// (name, content)
|
||||
let mut inputs = vec![];
|
||||
|
||||
if let Some(input) = test.config.get("inputs") {
|
||||
if let Value::Sequence(field) = input {
|
||||
for map in field {
|
||||
for (name, value) in map.as_mapping().unwrap().iter() {
|
||||
// Try to parse string from 'inputs' map, else fail
|
||||
let value = if let serde_yaml::Value::String(value) = value {
|
||||
value
|
||||
} else {
|
||||
return Err("Expected string in 'inputs' map".to_string());
|
||||
};
|
||||
if let Some(Value::Sequence(field)) = test.config.get("inputs") {
|
||||
for map in field {
|
||||
for (name, value) in map.as_mapping().unwrap().iter() {
|
||||
// Try to parse string from 'inputs' map, else fail
|
||||
let value = if let serde_yaml::Value::String(value) = value {
|
||||
value
|
||||
} else {
|
||||
return Err("Expected string in 'inputs' map".to_string());
|
||||
};
|
||||
|
||||
inputs.push((name.as_str().unwrap().to_string(), value.clone()));
|
||||
}
|
||||
inputs.push((name.as_str().unwrap().to_string(), value.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -180,15 +209,38 @@ impl Namespace for CompileNamespace {
|
||||
} else {
|
||||
last_circuit = Some(circuit);
|
||||
}
|
||||
|
||||
output_items.push(OutputItem {
|
||||
input_file: input.0,
|
||||
output,
|
||||
});
|
||||
}
|
||||
|
||||
let initial_ast: String = hash(
|
||||
Ast::from_json_file("/tmp/output/initial_ast.json".into())
|
||||
.unwrap_or_else(|_| Ast::new(Program::new("Error reading initial theorem.".to_string())))
|
||||
.to_json_string()
|
||||
.unwrap_or_else(|_| "Error converting ast to string.".to_string()),
|
||||
);
|
||||
let canonicalized_ast: String = hash(
|
||||
Ast::from_json_file("/tmp/output/canonicalization_ast.json".into())
|
||||
.unwrap_or_else(|_| Ast::new(Program::new("Error reading canonicalized theorem.".to_string())))
|
||||
.to_json_string()
|
||||
.unwrap_or_else(|_| "Error converting ast to string.".to_string()),
|
||||
);
|
||||
let type_inferenced_ast = hash(
|
||||
Ast::from_json_file("/tmp/output/type_inferenced_ast.json".into())
|
||||
.unwrap_or_else(|_| Ast::new(Program::new("Error reading type inferenced theorem.".to_string())))
|
||||
.to_json_string()
|
||||
.unwrap_or_else(|_| "Error converting ast to string.".to_string()),
|
||||
);
|
||||
|
||||
let final_output = CompileOutput {
|
||||
circuit: last_circuit.unwrap(),
|
||||
output: output_items,
|
||||
initial_ast,
|
||||
canonicalized_ast,
|
||||
type_inferenced_ast,
|
||||
};
|
||||
Ok(serde_yaml::to_value(&final_output).expect("serialization failed"))
|
||||
}
|
@ -1,359 +0,0 @@
|
||||
{
|
||||
"name": "",
|
||||
"expected_input": [],
|
||||
"imports": [],
|
||||
"circuits": {},
|
||||
"global_consts": {},
|
||||
"functions": {
|
||||
"{\"name\":\"main\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":10,\\\"col_stop\\\":14,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"function main(a: [group; (2, 1)]) {\\\"}\"}": {
|
||||
"annotations": [],
|
||||
"identifier": "{\"name\":\"main\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":10,\\\"col_stop\\\":14,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"function main(a: [group; (2, 1)]) {\\\"}\"}",
|
||||
"input": [
|
||||
{
|
||||
"Variable": {
|
||||
"identifier": "{\"name\":\"a\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":15,\\\"col_stop\\\":16,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"function main(a: [group; (2, 1)]) {\\\"}\"}",
|
||||
"const_": false,
|
||||
"mutable": true,
|
||||
"type_": {
|
||||
"Array": [
|
||||
{
|
||||
"Array": [
|
||||
"Group",
|
||||
[
|
||||
{
|
||||
"value": "1"
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
[
|
||||
{
|
||||
"value": "2"
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"span": {
|
||||
"line_start": 1,
|
||||
"line_stop": 1,
|
||||
"col_start": 15,
|
||||
"col_stop": 16,
|
||||
"path": "",
|
||||
"content": "function main(a: [group; (2, 1)]) {"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"output": {
|
||||
"Tuple": []
|
||||
},
|
||||
"block": {
|
||||
"statements": [
|
||||
{
|
||||
"Definition": {
|
||||
"declaration_type": "Let",
|
||||
"variable_names": [
|
||||
{
|
||||
"mutable": true,
|
||||
"identifier": "{\"name\":\"b\",\"span\":\"{\\\"line_start\\\":2,\\\"line_stop\\\":2,\\\"col_start\\\":7,\\\"col_stop\\\":8,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" let b = [true; (6, 5, 4, 3, 2)];\\\"}\"}",
|
||||
"span": {
|
||||
"line_start": 2,
|
||||
"line_stop": 2,
|
||||
"col_start": 7,
|
||||
"col_stop": 8,
|
||||
"path": "",
|
||||
"content": " let b = [true; (6, 5, 4, 3, 2)];"
|
||||
}
|
||||
}
|
||||
],
|
||||
"type_": null,
|
||||
"value": {
|
||||
"ArrayInit": {
|
||||
"element": {
|
||||
"ArrayInit": {
|
||||
"element": {
|
||||
"ArrayInit": {
|
||||
"element": {
|
||||
"ArrayInit": {
|
||||
"element": {
|
||||
"ArrayInit": {
|
||||
"element": {
|
||||
"Value": {
|
||||
"Boolean": [
|
||||
"true",
|
||||
{
|
||||
"line_start": 2,
|
||||
"line_stop": 2,
|
||||
"col_start": 12,
|
||||
"col_stop": 16,
|
||||
"path": "",
|
||||
"content": " let b = [true; (6, 5, 4, 3, 2)];"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"dimensions": [
|
||||
{
|
||||
"value": "2"
|
||||
}
|
||||
],
|
||||
"span": {
|
||||
"line_start": 2,
|
||||
"line_stop": 2,
|
||||
"col_start": 11,
|
||||
"col_stop": 34,
|
||||
"path": "",
|
||||
"content": " let b = [true; (6, 5, 4, 3, 2)];"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dimensions": [
|
||||
{
|
||||
"value": "3"
|
||||
}
|
||||
],
|
||||
"span": {
|
||||
"line_start": 2,
|
||||
"line_stop": 2,
|
||||
"col_start": 11,
|
||||
"col_stop": 34,
|
||||
"path": "",
|
||||
"content": " let b = [true; (6, 5, 4, 3, 2)];"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dimensions": [
|
||||
{
|
||||
"value": "4"
|
||||
}
|
||||
],
|
||||
"span": {
|
||||
"line_start": 2,
|
||||
"line_stop": 2,
|
||||
"col_start": 11,
|
||||
"col_stop": 34,
|
||||
"path": "",
|
||||
"content": " let b = [true; (6, 5, 4, 3, 2)];"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dimensions": [
|
||||
{
|
||||
"value": "5"
|
||||
}
|
||||
],
|
||||
"span": {
|
||||
"line_start": 2,
|
||||
"line_stop": 2,
|
||||
"col_start": 11,
|
||||
"col_stop": 34,
|
||||
"path": "",
|
||||
"content": " let b = [true; (6, 5, 4, 3, 2)];"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dimensions": [
|
||||
{
|
||||
"value": "6"
|
||||
}
|
||||
],
|
||||
"span": {
|
||||
"line_start": 2,
|
||||
"line_stop": 2,
|
||||
"col_start": 11,
|
||||
"col_stop": 34,
|
||||
"path": "",
|
||||
"content": " let b = [true; (6, 5, 4, 3, 2)];"
|
||||
}
|
||||
}
|
||||
},
|
||||
"span": {
|
||||
"line_start": 2,
|
||||
"line_stop": 2,
|
||||
"col_start": 3,
|
||||
"col_stop": 34,
|
||||
"path": "",
|
||||
"content": " let b = [true; (6, 5, 4, 3, 2)];"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Definition": {
|
||||
"declaration_type": "Let",
|
||||
"variable_names": [
|
||||
{
|
||||
"mutable": true,
|
||||
"identifier": "{\"name\":\"c\",\"span\":\"{\\\"line_start\\\":3,\\\"line_stop\\\":3,\\\"col_start\\\":7,\\\"col_stop\\\":8,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" let c: [u32; (1, 2)] = [0u32; (1, 2)];\\\"}\"}",
|
||||
"span": {
|
||||
"line_start": 3,
|
||||
"line_stop": 3,
|
||||
"col_start": 7,
|
||||
"col_stop": 8,
|
||||
"path": "",
|
||||
"content": " let c: [u32; (1, 2)] = [0u32; (1, 2)];"
|
||||
}
|
||||
}
|
||||
],
|
||||
"type_": {
|
||||
"Array": [
|
||||
{
|
||||
"Array": [
|
||||
{
|
||||
"IntegerType": "U32"
|
||||
},
|
||||
[
|
||||
{
|
||||
"value": "2"
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
[
|
||||
{
|
||||
"value": "1"
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"value": {
|
||||
"ArrayInit": {
|
||||
"element": {
|
||||
"ArrayInit": {
|
||||
"element": {
|
||||
"Value": {
|
||||
"Integer": [
|
||||
"U32",
|
||||
"0",
|
||||
{
|
||||
"line_start": 3,
|
||||
"line_stop": 3,
|
||||
"col_start": 27,
|
||||
"col_stop": 31,
|
||||
"path": "",
|
||||
"content": " let c: [u32; (1, 2)] = [0u32; (1, 2)];"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"dimensions": [
|
||||
{
|
||||
"value": "2"
|
||||
}
|
||||
],
|
||||
"span": {
|
||||
"line_start": 3,
|
||||
"line_stop": 3,
|
||||
"col_start": 26,
|
||||
"col_stop": 40,
|
||||
"path": "",
|
||||
"content": " let c: [u32; (1, 2)] = [0u32; (1, 2)];"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dimensions": [
|
||||
{
|
||||
"value": "1"
|
||||
}
|
||||
],
|
||||
"span": {
|
||||
"line_start": 3,
|
||||
"line_stop": 3,
|
||||
"col_start": 26,
|
||||
"col_stop": 40,
|
||||
"path": "",
|
||||
"content": " let c: [u32; (1, 2)] = [0u32; (1, 2)];"
|
||||
}
|
||||
}
|
||||
},
|
||||
"span": {
|
||||
"line_start": 3,
|
||||
"line_stop": 3,
|
||||
"col_start": 3,
|
||||
"col_stop": 40,
|
||||
"path": "",
|
||||
"content": " let c: [u32; (1, 2)] = [0u32; (1, 2)];"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Definition": {
|
||||
"declaration_type": "Let",
|
||||
"variable_names": [
|
||||
{
|
||||
"mutable": true,
|
||||
"identifier": "{\"name\":\"d\",\"span\":\"{\\\"line_start\\\":4,\\\"line_stop\\\":4,\\\"col_start\\\":7,\\\"col_stop\\\":8,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" let d = [0i8; (1)];\\\"}\"}",
|
||||
"span": {
|
||||
"line_start": 4,
|
||||
"line_stop": 4,
|
||||
"col_start": 7,
|
||||
"col_stop": 8,
|
||||
"path": "",
|
||||
"content": " let d = [0i8; (1)];"
|
||||
}
|
||||
}
|
||||
],
|
||||
"type_": null,
|
||||
"value": {
|
||||
"ArrayInit": {
|
||||
"element": {
|
||||
"Value": {
|
||||
"Integer": [
|
||||
"I8",
|
||||
"0",
|
||||
{
|
||||
"line_start": 4,
|
||||
"line_stop": 4,
|
||||
"col_start": 12,
|
||||
"col_stop": 15,
|
||||
"path": "",
|
||||
"content": " let d = [0i8; (1)];"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"dimensions": [
|
||||
{
|
||||
"value": "1"
|
||||
}
|
||||
],
|
||||
"span": {
|
||||
"line_start": 4,
|
||||
"line_stop": 4,
|
||||
"col_start": 11,
|
||||
"col_stop": 21,
|
||||
"path": "",
|
||||
"content": " let d = [0i8; (1)];"
|
||||
}
|
||||
}
|
||||
},
|
||||
"span": {
|
||||
"line_start": 4,
|
||||
"line_stop": 4,
|
||||
"col_start": 3,
|
||||
"col_stop": 21,
|
||||
"path": "",
|
||||
"content": " let d = [0i8; (1)];"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"span": {
|
||||
"line_start": 1,
|
||||
"line_stop": 7,
|
||||
"col_start": 35,
|
||||
"col_stop": 2,
|
||||
"path": "",
|
||||
"content": "function main(a: [group; (2, 1)]) {\n...\n}"
|
||||
}
|
||||
},
|
||||
"span": {
|
||||
"line_start": 1,
|
||||
"line_stop": 7,
|
||||
"col_start": 1,
|
||||
"col_stop": 2,
|
||||
"path": "",
|
||||
"content": "function main(a: [group; (2, 1)]) {\n...\n}\n\n\n\n"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
function main(a: [group; (2, 1)]) {
|
||||
let b = [true; (6, 5, 4, 3, 2)];
|
||||
let c: [u32; (1, 2)] = [0u32; (1, 2)];
|
||||
let d = [0i8; (1)];
|
||||
// let d = [true; 0];
|
||||
// let e = [true; (0)];
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
function main() {
|
||||
let a = [true; (0)];
|
||||
}
|
@ -1,438 +0,0 @@
|
||||
{
|
||||
"name": "",
|
||||
"expected_input": [],
|
||||
"imports": [],
|
||||
"circuits": {
|
||||
"{\"name\":\"Foo\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":9,\\\"col_stop\\\":12,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"circuit Foo {\\\"}\"}": {
|
||||
"circuit_name": "{\"name\":\"Foo\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":9,\\\"col_stop\\\":12,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"circuit Foo {\\\"}\"}",
|
||||
"members": [
|
||||
{
|
||||
"CircuitVariable": [
|
||||
"{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":2,\\\"line_stop\\\":2,\\\"col_start\\\":3,\\\"col_stop\\\":4,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" x: u32;\\\"}\"}",
|
||||
{
|
||||
"IntegerType": "U32"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"CircuitFunction": {
|
||||
"annotations": [],
|
||||
"identifier": "{\"name\":\"new\",\"span\":\"{\\\"line_start\\\":4,\\\"line_stop\\\":4,\\\"col_start\\\":12,\\\"col_stop\\\":15,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" function new() -> Self {\\\"}\"}",
|
||||
"input": [],
|
||||
"output": {
|
||||
"Circuit": "{\"name\":\"Foo\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":9,\\\"col_stop\\\":12,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"circuit Foo {\\\"}\"}"
|
||||
},
|
||||
"block": {
|
||||
"statements": [
|
||||
{
|
||||
"Definition": {
|
||||
"declaration_type": "Let",
|
||||
"variable_names": [
|
||||
{
|
||||
"mutable": true,
|
||||
"identifier": "{\"name\":\"new\",\"span\":\"{\\\"line_start\\\":5,\\\"line_stop\\\":5,\\\"col_start\\\":9,\\\"col_stop\\\":12,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" let new: Self = Self {\\\"}\"}",
|
||||
"span": {
|
||||
"line_start": 5,
|
||||
"line_stop": 5,
|
||||
"col_start": 9,
|
||||
"col_stop": 12,
|
||||
"path": "",
|
||||
"content": " let new: Self = Self {"
|
||||
}
|
||||
}
|
||||
],
|
||||
"type_": {
|
||||
"Circuit": "{\"name\":\"Foo\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":9,\\\"col_stop\\\":12,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"circuit Foo {\\\"}\"}"
|
||||
},
|
||||
"value": {
|
||||
"CircuitInit": {
|
||||
"name": "{\"name\":\"Foo\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":9,\\\"col_stop\\\":12,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"circuit Foo {\\\"}\"}",
|
||||
"members": [
|
||||
{
|
||||
"identifier": "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":6,\\\"line_stop\\\":6,\\\"col_start\\\":7,\\\"col_stop\\\":8,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" x: 1u32\\\"}\"}",
|
||||
"expression": {
|
||||
"Value": {
|
||||
"Integer": [
|
||||
"U32",
|
||||
"1",
|
||||
{
|
||||
"line_start": 6,
|
||||
"line_stop": 6,
|
||||
"col_start": 10,
|
||||
"col_stop": 14,
|
||||
"path": "",
|
||||
"content": " x: 1u32"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"span": {
|
||||
"line_start": 5,
|
||||
"line_stop": 7,
|
||||
"col_start": 21,
|
||||
"col_stop": 6,
|
||||
"path": "",
|
||||
"content": " let new: Self = Self {\n...\n };"
|
||||
}
|
||||
}
|
||||
},
|
||||
"span": {
|
||||
"line_start": 5,
|
||||
"line_stop": 7,
|
||||
"col_start": 5,
|
||||
"col_stop": 6,
|
||||
"path": "",
|
||||
"content": " let new: Self = Self {\n...\n };"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Return": {
|
||||
"expression": {
|
||||
"Identifier": "{\"name\":\"new\",\"span\":\"{\\\"line_start\\\":9,\\\"line_stop\\\":9,\\\"col_start\\\":12,\\\"col_stop\\\":15,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" return new;\\\"}\"}"
|
||||
},
|
||||
"span": {
|
||||
"line_start": 9,
|
||||
"line_stop": 9,
|
||||
"col_start": 5,
|
||||
"col_stop": 15,
|
||||
"path": "",
|
||||
"content": " return new;"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"span": {
|
||||
"line_start": 4,
|
||||
"line_stop": 10,
|
||||
"col_start": 26,
|
||||
"col_stop": 4,
|
||||
"path": "",
|
||||
"content": " function new() -> Self {\n...\n }"
|
||||
}
|
||||
},
|
||||
"span": {
|
||||
"line_start": 4,
|
||||
"line_stop": 10,
|
||||
"col_start": 3,
|
||||
"col_stop": 4,
|
||||
"path": "",
|
||||
"content": " function new() -> Self {\n...\n }\n\n\n\n"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"CircuitFunction": {
|
||||
"annotations": [],
|
||||
"identifier": "{\"name\":\"etc\",\"span\":\"{\\\"line_start\\\":12,\\\"line_stop\\\":12,\\\"col_start\\\":12,\\\"col_stop\\\":15,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" function etc() {\\\"}\"}",
|
||||
"input": [],
|
||||
"output": {
|
||||
"Tuple": []
|
||||
},
|
||||
"block": {
|
||||
"statements": [
|
||||
{
|
||||
"Assign": {
|
||||
"operation": "Assign",
|
||||
"assignee": {
|
||||
"identifier": "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":13,\\\"line_stop\\\":13,\\\"col_start\\\":6,\\\"col_stop\\\":7,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" y[Self {x: 0}.func()] += 2;\\\"}\"}",
|
||||
"accesses": [
|
||||
{
|
||||
"ArrayIndex": {
|
||||
"Call": {
|
||||
"function": {
|
||||
"CircuitMemberAccess": {
|
||||
"circuit": {
|
||||
"CircuitInit": {
|
||||
"name": "{\"name\":\"Foo\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":9,\\\"col_stop\\\":12,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"circuit Foo {\\\"}\"}",
|
||||
"members": [
|
||||
{
|
||||
"identifier": "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":13,\\\"line_stop\\\":13,\\\"col_start\\\":14,\\\"col_stop\\\":15,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" y[Self {x: 0}.func()] += 2;\\\"}\"}",
|
||||
"expression": {
|
||||
"Value": {
|
||||
"Implicit": [
|
||||
"0",
|
||||
{
|
||||
"line_start": 13,
|
||||
"line_stop": 13,
|
||||
"col_start": 17,
|
||||
"col_stop": 18,
|
||||
"path": "",
|
||||
"content": " y[Self {x: 0}.func()] += 2;"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"span": {
|
||||
"line_start": 13,
|
||||
"line_stop": 13,
|
||||
"col_start": 8,
|
||||
"col_stop": 19,
|
||||
"path": "",
|
||||
"content": " y[Self {x: 0}.func()] += 2;"
|
||||
}
|
||||
}
|
||||
},
|
||||
"name": "{\"name\":\"func\",\"span\":\"{\\\"line_start\\\":13,\\\"line_stop\\\":13,\\\"col_start\\\":20,\\\"col_stop\\\":24,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" y[Self {x: 0}.func()] += 2;\\\"}\"}",
|
||||
"span": {
|
||||
"line_start": 13,
|
||||
"line_stop": 13,
|
||||
"col_start": 8,
|
||||
"col_stop": 24,
|
||||
"path": "",
|
||||
"content": " y[Self {x: 0}.func()] += 2;"
|
||||
}
|
||||
}
|
||||
},
|
||||
"arguments": [],
|
||||
"span": {
|
||||
"line_start": 13,
|
||||
"line_stop": 13,
|
||||
"col_start": 8,
|
||||
"col_stop": 26,
|
||||
"path": "",
|
||||
"content": " y[Self {x: 0}.func()] += 2;"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"span": {
|
||||
"line_start": 13,
|
||||
"line_stop": 13,
|
||||
"col_start": 6,
|
||||
"col_stop": 27,
|
||||
"path": "",
|
||||
"content": " y[Self {x: 0}.func()] += 2;"
|
||||
}
|
||||
},
|
||||
"value": {
|
||||
"Binary": {
|
||||
"left": {
|
||||
"ArrayAccess": {
|
||||
"array": {
|
||||
"Identifier": "{\"name\":\"y\",\"span\":\"{\\\"line_start\\\":13,\\\"line_stop\\\":13,\\\"col_start\\\":6,\\\"col_stop\\\":7,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" y[Self {x: 0}.func()] += 2;\\\"}\"}"
|
||||
},
|
||||
"index": {
|
||||
"Call": {
|
||||
"function": {
|
||||
"CircuitMemberAccess": {
|
||||
"circuit": {
|
||||
"CircuitInit": {
|
||||
"name": "{\"name\":\"Foo\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":9,\\\"col_stop\\\":12,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"circuit Foo {\\\"}\"}",
|
||||
"members": [
|
||||
{
|
||||
"identifier": "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":13,\\\"line_stop\\\":13,\\\"col_start\\\":14,\\\"col_stop\\\":15,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" y[Self {x: 0}.func()] += 2;\\\"}\"}",
|
||||
"expression": {
|
||||
"Value": {
|
||||
"Implicit": [
|
||||
"0",
|
||||
{
|
||||
"line_start": 13,
|
||||
"line_stop": 13,
|
||||
"col_start": 17,
|
||||
"col_stop": 18,
|
||||
"path": "",
|
||||
"content": " y[Self {x: 0}.func()] += 2;"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"span": {
|
||||
"line_start": 13,
|
||||
"line_stop": 13,
|
||||
"col_start": 8,
|
||||
"col_stop": 19,
|
||||
"path": "",
|
||||
"content": " y[Self {x: 0}.func()] += 2;"
|
||||
}
|
||||
}
|
||||
},
|
||||
"name": "{\"name\":\"func\",\"span\":\"{\\\"line_start\\\":13,\\\"line_stop\\\":13,\\\"col_start\\\":20,\\\"col_stop\\\":24,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" y[Self {x: 0}.func()] += 2;\\\"}\"}",
|
||||
"span": {
|
||||
"line_start": 13,
|
||||
"line_stop": 13,
|
||||
"col_start": 8,
|
||||
"col_stop": 24,
|
||||
"path": "",
|
||||
"content": " y[Self {x: 0}.func()] += 2;"
|
||||
}
|
||||
}
|
||||
},
|
||||
"arguments": [],
|
||||
"span": {
|
||||
"line_start": 13,
|
||||
"line_stop": 13,
|
||||
"col_start": 8,
|
||||
"col_stop": 26,
|
||||
"path": "",
|
||||
"content": " y[Self {x: 0}.func()] += 2;"
|
||||
}
|
||||
}
|
||||
},
|
||||
"span": {
|
||||
"line_start": 13,
|
||||
"line_stop": 13,
|
||||
"col_start": 6,
|
||||
"col_stop": 32,
|
||||
"path": "",
|
||||
"content": " y[Self {x: 0}.func()] += 2;"
|
||||
}
|
||||
}
|
||||
},
|
||||
"right": {
|
||||
"Value": {
|
||||
"Implicit": [
|
||||
"2",
|
||||
{
|
||||
"line_start": 13,
|
||||
"line_stop": 13,
|
||||
"col_start": 31,
|
||||
"col_stop": 32,
|
||||
"path": "",
|
||||
"content": " y[Self {x: 0}.func()] += 2;"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"op": "Add",
|
||||
"span": {
|
||||
"line_start": 13,
|
||||
"line_stop": 13,
|
||||
"col_start": 6,
|
||||
"col_stop": 32,
|
||||
"path": "",
|
||||
"content": " y[Self {x: 0}.func()] += 2;"
|
||||
}
|
||||
}
|
||||
},
|
||||
"span": {
|
||||
"line_start": 13,
|
||||
"line_stop": 13,
|
||||
"col_start": 6,
|
||||
"col_stop": 32,
|
||||
"path": "",
|
||||
"content": " y[Self {x: 0}.func()] += 2;"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"span": {
|
||||
"line_start": 12,
|
||||
"line_stop": 14,
|
||||
"col_start": 18,
|
||||
"col_stop": 4,
|
||||
"path": "",
|
||||
"content": " function etc() {\n...\n }"
|
||||
}
|
||||
},
|
||||
"span": {
|
||||
"line_start": 12,
|
||||
"line_stop": 14,
|
||||
"col_start": 3,
|
||||
"col_stop": 4,
|
||||
"path": "",
|
||||
"content": " function etc() {\n...\n }"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"global_consts": {},
|
||||
"functions": {
|
||||
"{\"name\":\"main\",\"span\":\"{\\\"line_start\\\":17,\\\"line_stop\\\":17,\\\"col_start\\\":10,\\\"col_stop\\\":14,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"function main() {\\\"}\"}": {
|
||||
"annotations": [],
|
||||
"identifier": "{\"name\":\"main\",\"span\":\"{\\\"line_start\\\":17,\\\"line_stop\\\":17,\\\"col_start\\\":10,\\\"col_stop\\\":14,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"function main() {\\\"}\"}",
|
||||
"input": [],
|
||||
"output": {
|
||||
"Tuple": []
|
||||
},
|
||||
"block": {
|
||||
"statements": [
|
||||
{
|
||||
"Definition": {
|
||||
"declaration_type": "Let",
|
||||
"variable_names": [
|
||||
{
|
||||
"mutable": true,
|
||||
"identifier": "{\"name\":\"foo\",\"span\":\"{\\\"line_start\\\":18,\\\"line_stop\\\":18,\\\"col_start\\\":7,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" let foo: Foo = Foo::new();\\\"}\"}",
|
||||
"span": {
|
||||
"line_start": 18,
|
||||
"line_stop": 18,
|
||||
"col_start": 7,
|
||||
"col_stop": 10,
|
||||
"path": "",
|
||||
"content": " let foo: Foo = Foo::new();"
|
||||
}
|
||||
}
|
||||
],
|
||||
"type_": {
|
||||
"Circuit": "{\"name\":\"Foo\",\"span\":\"{\\\"line_start\\\":18,\\\"line_stop\\\":18,\\\"col_start\\\":12,\\\"col_stop\\\":15,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" let foo: Foo = Foo::new();\\\"}\"}"
|
||||
},
|
||||
"value": {
|
||||
"Call": {
|
||||
"function": {
|
||||
"CircuitStaticFunctionAccess": {
|
||||
"circuit": {
|
||||
"Identifier": "{\"name\":\"Foo\",\"span\":\"{\\\"line_start\\\":18,\\\"line_stop\\\":18,\\\"col_start\\\":18,\\\"col_stop\\\":21,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" let foo: Foo = Foo::new();\\\"}\"}"
|
||||
},
|
||||
"name": "{\"name\":\"new\",\"span\":\"{\\\"line_start\\\":18,\\\"line_stop\\\":18,\\\"col_start\\\":23,\\\"col_stop\\\":26,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" let foo: Foo = Foo::new();\\\"}\"}",
|
||||
"span": {
|
||||
"line_start": 18,
|
||||
"line_stop": 18,
|
||||
"col_start": 18,
|
||||
"col_stop": 26,
|
||||
"path": "",
|
||||
"content": " let foo: Foo = Foo::new();"
|
||||
}
|
||||
}
|
||||
},
|
||||
"arguments": [],
|
||||
"span": {
|
||||
"line_start": 18,
|
||||
"line_stop": 18,
|
||||
"col_start": 18,
|
||||
"col_stop": 28,
|
||||
"path": "",
|
||||
"content": " let foo: Foo = Foo::new();"
|
||||
}
|
||||
}
|
||||
},
|
||||
"span": {
|
||||
"line_start": 18,
|
||||
"line_stop": 18,
|
||||
"col_start": 3,
|
||||
"col_stop": 28,
|
||||
"path": "",
|
||||
"content": " let foo: Foo = Foo::new();"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"span": {
|
||||
"line_start": 17,
|
||||
"line_stop": 19,
|
||||
"col_start": 17,
|
||||
"col_stop": 2,
|
||||
"path": "",
|
||||
"content": "function main() {\n...\n}"
|
||||
}
|
||||
},
|
||||
"span": {
|
||||
"line_start": 17,
|
||||
"line_stop": 19,
|
||||
"col_start": 1,
|
||||
"col_stop": 2,
|
||||
"path": "",
|
||||
"content": "function main() {\n...\n}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
circuit Foo {
|
||||
x: u32;
|
||||
|
||||
function new() -> Self {
|
||||
let new: Self = Self {
|
||||
x: 1u32
|
||||
};
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
function etc() {
|
||||
y[Self {x: 0}.func()] += 2;
|
||||
}
|
||||
}
|
||||
|
||||
function main() {
|
||||
let foo: Foo = Foo::new();
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +0,0 @@
|
||||
function main () {
|
||||
let x = [1u32; 5];
|
||||
x[..2] += 1;
|
||||
}
|
@ -1,2 +0,0 @@
|
||||
[main]
|
||||
a: [group; (2, 1)] = [1group; (2, 1)];
|
@ -1,97 +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::parse_program;
|
||||
use leo_ast::Ast;
|
||||
use leo_parser::parser;
|
||||
|
||||
pub fn parse_program_ast(file_string: &str) -> Ast {
|
||||
const TEST_PROGRAM_PATH: &str = "";
|
||||
let test_program_file_path = std::path::PathBuf::from(TEST_PROGRAM_PATH);
|
||||
|
||||
let mut ast = Ast::new(
|
||||
parser::parse(test_program_file_path.to_str().expect("unwrap fail"), &file_string)
|
||||
.expect("Failed to parse file."),
|
||||
);
|
||||
ast.canonicalize().expect("Failed to canonicalize program.");
|
||||
|
||||
ast
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_big_self_in_circuit_replacement() {
|
||||
// Check program is valid.
|
||||
let program_string = include_str!("big_self_in_circuit_replacement.leo");
|
||||
// Check we get expected ast.
|
||||
let ast = parse_program_ast(program_string);
|
||||
let expected_json = include_str!("big_self_in_circuit_replacement.json");
|
||||
let expected_ast: Ast = Ast::from_json_string(expected_json).expect("Unable to parse json.");
|
||||
|
||||
assert_eq!(expected_ast, ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_big_self_outside_circuit_fail() {
|
||||
// Check program is invalid.
|
||||
let program_string = include_str!("big_self_outside_circuit_fail.leo");
|
||||
let program = parse_program(program_string);
|
||||
assert!(program.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_array_expansion() {
|
||||
let program_string = include_str!("array_expansion.leo");
|
||||
let ast = parse_program_ast(program_string);
|
||||
let expected_json = include_str!("array_expansion.json");
|
||||
let expected_ast: Ast = Ast::from_json_string(expected_json).expect("Unable to parse json.");
|
||||
|
||||
assert_eq!(expected_ast, ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_array_size_zero_fail() {
|
||||
let program_string = include_str!("array_size_zero_fail.leo");
|
||||
let program = parse_program(program_string);
|
||||
assert!(program.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_compound_assignment() {
|
||||
let program_string = include_str!("compound_assignment.leo");
|
||||
let ast = parse_program_ast(program_string);
|
||||
let expected_json = include_str!("compound_assignment.json");
|
||||
let expected_ast: Ast = Ast::from_json_string(expected_json).expect("Unable to parse json.");
|
||||
|
||||
assert_eq!(expected_ast, ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_illegal_array_range_fail() {
|
||||
// Check program is invalid.
|
||||
let program_string = include_str!("illegal_array_range_fail.leo");
|
||||
let program = parse_program(program_string);
|
||||
assert!(program.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_string_transformation() {
|
||||
let program_string = include_str!("string_transformation.leo");
|
||||
let ast = parse_program_ast(program_string);
|
||||
let expected_json = include_str!("string_transformation.json");
|
||||
let expected_ast: Ast = Ast::from_json_string(expected_json).expect("Unable to parse json.");
|
||||
|
||||
assert_eq!(expected_ast, ast);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,8 +0,0 @@
|
||||
function main() {
|
||||
let s = "\u{2764}ello, World!\u{DDDD}";
|
||||
s[..2] = "he";
|
||||
let x = false;
|
||||
x = "test1" == "test2";
|
||||
let z = [1u8, 2u8, 3u8, 4u8];
|
||||
z[0.."test" == "test"? 2 : 2] = x[0..2];
|
||||
}
|
@ -1 +0,0 @@
|
||||
[registers]
|
@ -1,131 +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/>.
|
||||
|
||||
// allow the use of EdwardsTestCompiler::parse_program_from_string for tests
|
||||
|
||||
#![allow(deprecated)]
|
||||
|
||||
pub mod canonicalization;
|
||||
pub mod type_inference;
|
||||
|
||||
use leo_asg::{new_alloc_context, new_context, AsgContext};
|
||||
use leo_compiler::{
|
||||
compiler::Compiler,
|
||||
errors::CompilerError,
|
||||
group::targets::edwards_bls12::EdwardsGroupType,
|
||||
ConstrainedValue,
|
||||
OutputBytes,
|
||||
};
|
||||
|
||||
use snarkvm_curves::edwards_bls12::Fq;
|
||||
use snarkvm_r1cs::TestConstraintSystem;
|
||||
|
||||
use std::{collections::HashMap, path::PathBuf};
|
||||
|
||||
pub const TEST_OUTPUT_DIRECTORY: &str = "/output/";
|
||||
const EMPTY_FILE: &str = "";
|
||||
|
||||
pub type EdwardsTestCompiler = Compiler<'static, Fq, EdwardsGroupType>;
|
||||
pub type EdwardsConstrainedValue = ConstrainedValue<'static, Fq, EdwardsGroupType>;
|
||||
|
||||
//convenience function for tests, leaks memory
|
||||
pub(crate) fn make_test_context() -> AsgContext<'static> {
|
||||
let allocator = Box::leak(Box::new(new_alloc_context()));
|
||||
new_context(allocator)
|
||||
}
|
||||
|
||||
fn new_compiler() -> EdwardsTestCompiler {
|
||||
let program_name = "test".to_string();
|
||||
let path = PathBuf::from("/test/src/main.leo");
|
||||
let output_dir = PathBuf::from(TEST_OUTPUT_DIRECTORY);
|
||||
|
||||
EdwardsTestCompiler::new(
|
||||
program_name,
|
||||
path,
|
||||
output_dir,
|
||||
make_test_context(),
|
||||
None,
|
||||
None,
|
||||
HashMap::new(),
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn parse_program(program_string: &str) -> Result<EdwardsTestCompiler, CompilerError> {
|
||||
let mut compiler = new_compiler();
|
||||
|
||||
compiler.parse_program_from_string(program_string)?;
|
||||
|
||||
Ok(compiler)
|
||||
}
|
||||
|
||||
pub fn parse_program_with_input(
|
||||
program_string: &str,
|
||||
input_string: &str,
|
||||
) -> Result<EdwardsTestCompiler, CompilerError> {
|
||||
let mut compiler = new_compiler();
|
||||
let path = PathBuf::new();
|
||||
|
||||
compiler.parse_input(input_string, &path, EMPTY_FILE, &path)?;
|
||||
compiler.parse_program_from_string(program_string)?;
|
||||
|
||||
Ok(compiler)
|
||||
}
|
||||
|
||||
pub fn parse_program_with_state(
|
||||
program_string: &str,
|
||||
state_string: &str,
|
||||
) -> Result<EdwardsTestCompiler, CompilerError> {
|
||||
let mut compiler = new_compiler();
|
||||
let path = PathBuf::new();
|
||||
|
||||
compiler.parse_input(EMPTY_FILE, &path, state_string, &path)?;
|
||||
compiler.parse_program_from_string(program_string)?;
|
||||
|
||||
Ok(compiler)
|
||||
}
|
||||
|
||||
pub fn parse_program_with_input_and_state(
|
||||
program_string: &str,
|
||||
input_string: &str,
|
||||
state_string: &str,
|
||||
) -> Result<EdwardsTestCompiler, CompilerError> {
|
||||
let mut compiler = new_compiler();
|
||||
let path = PathBuf::new();
|
||||
|
||||
compiler.parse_input(input_string, &path, state_string, &path)?;
|
||||
compiler.parse_program_from_string(&program_string)?;
|
||||
|
||||
Ok(compiler)
|
||||
}
|
||||
|
||||
pub(crate) fn get_output(program: EdwardsTestCompiler) -> OutputBytes {
|
||||
// synthesize the circuit on the test constraint system
|
||||
let mut cs = TestConstraintSystem::<Fq>::new();
|
||||
let output = program.compile_constraints(&mut cs).unwrap();
|
||||
|
||||
// assert the constraint system is satisfied
|
||||
assert!(cs.is_satisfied());
|
||||
|
||||
output.into()
|
||||
}
|
||||
|
||||
pub(crate) fn assert_satisfied(program: EdwardsTestCompiler) {
|
||||
let empty_output_bytes = include_bytes!("compiler_output/empty.out");
|
||||
let res = get_output(program);
|
||||
|
||||
// assert that the output is empty
|
||||
assert_eq!(empty_output_bytes, res.bytes().as_slice());
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,27 +0,0 @@
|
||||
circuit Foo {}
|
||||
|
||||
function two() -> u8 {
|
||||
return 2u8;
|
||||
}
|
||||
|
||||
const ONE = 1u8;
|
||||
|
||||
function main() {
|
||||
const a = 1u8;
|
||||
const b = 1field;
|
||||
const c = 1group;
|
||||
const d = (0, 1)group;
|
||||
const e = aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8sta57j8;
|
||||
const f = two();
|
||||
const g = [0u8; (3, 2)];
|
||||
const h = [[0u8; 3]; 2];
|
||||
const i = [1u8, 1u8, 1u8];
|
||||
const j = true;
|
||||
const k = (1u8, 1u8);
|
||||
const l = (1u8, 1u8, true);
|
||||
const m = Foo {};
|
||||
const n = 'a';
|
||||
const o = "Hello, World!";
|
||||
const p = [...[1u8], ...[2u8]];
|
||||
const q = [...p, 3u8] == [1u8, 2u8, 3u8];
|
||||
}
|
@ -1,243 +0,0 @@
|
||||
{
|
||||
"name": "",
|
||||
"expected_input": [],
|
||||
"imports": [],
|
||||
"circuits": {},
|
||||
"global_consts": {},
|
||||
"functions": {
|
||||
"{\"name\":\"main\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":10,\\\"col_stop\\\":14,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"function main() {\\\"}\"}": {
|
||||
"annotations": [],
|
||||
"identifier": "{\"name\":\"main\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":10,\\\"col_stop\\\":14,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\"function main() {\\\"}\"}",
|
||||
"input": [],
|
||||
"output": {
|
||||
"Tuple": []
|
||||
},
|
||||
"block": {
|
||||
"statements": [
|
||||
{
|
||||
"Definition": {
|
||||
"declaration_type": "Let",
|
||||
"variable_names": [
|
||||
{
|
||||
"mutable": true,
|
||||
"identifier": "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":2,\\\"line_stop\\\":2,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" let x = 10u16;\\\"}\"}",
|
||||
"span": {
|
||||
"line_start": 2,
|
||||
"line_stop": 2,
|
||||
"col_start": 9,
|
||||
"col_stop": 10,
|
||||
"path": "",
|
||||
"content": " let x = 10u16;"
|
||||
}
|
||||
}
|
||||
],
|
||||
"type_": {
|
||||
"IntegerType": "U16"
|
||||
},
|
||||
"value": {
|
||||
"Value": {
|
||||
"Integer": [
|
||||
"U16",
|
||||
"10",
|
||||
{
|
||||
"line_start": 2,
|
||||
"line_stop": 2,
|
||||
"col_start": 13,
|
||||
"col_stop": 18,
|
||||
"path": "",
|
||||
"content": " let x = 10u16;"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"span": {
|
||||
"line_start": 2,
|
||||
"line_stop": 2,
|
||||
"col_start": 5,
|
||||
"col_stop": 18,
|
||||
"path": "",
|
||||
"content": " let x = 10u16;"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Iteration": {
|
||||
"variable": "{\"name\":\"i\",\"span\":\"{\\\"line_start\\\":3,\\\"line_stop\\\":3,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" for i in 0..3 {\\\"}\"}",
|
||||
"start": {
|
||||
"Value": {
|
||||
"Integer": [
|
||||
"U32",
|
||||
"0",
|
||||
{
|
||||
"line_start": 3,
|
||||
"line_stop": 3,
|
||||
"col_start": 14,
|
||||
"col_stop": 15,
|
||||
"path": "",
|
||||
"content": " for i in 0..3 {"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"stop": {
|
||||
"Value": {
|
||||
"Integer": [
|
||||
"U32",
|
||||
"3",
|
||||
{
|
||||
"line_start": 3,
|
||||
"line_stop": 3,
|
||||
"col_start": 17,
|
||||
"col_stop": 18,
|
||||
"path": "",
|
||||
"content": " for i in 0..3 {"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"block": {
|
||||
"statements": [
|
||||
{
|
||||
"Assign": {
|
||||
"operation": "Assign",
|
||||
"assignee": {
|
||||
"identifier": "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":4,\\\"line_stop\\\":4,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" x -= 1;\\\"}\"}",
|
||||
"accesses": [],
|
||||
"span": {
|
||||
"line_start": 4,
|
||||
"line_stop": 4,
|
||||
"col_start": 9,
|
||||
"col_stop": 10,
|
||||
"path": "",
|
||||
"content": " x -= 1;"
|
||||
}
|
||||
},
|
||||
"value": {
|
||||
"Binary": {
|
||||
"left": {
|
||||
"Identifier": "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":4,\\\"line_stop\\\":4,\\\"col_start\\\":9,\\\"col_stop\\\":10,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" x -= 1;\\\"}\"}"
|
||||
},
|
||||
"right": {
|
||||
"Value": {
|
||||
"Integer": [
|
||||
"U16",
|
||||
"1",
|
||||
{
|
||||
"line_start": 4,
|
||||
"line_stop": 4,
|
||||
"col_start": 14,
|
||||
"col_stop": 15,
|
||||
"path": "",
|
||||
"content": " x -= 1;"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"op": "Sub",
|
||||
"span": {
|
||||
"line_start": 4,
|
||||
"line_stop": 4,
|
||||
"col_start": 9,
|
||||
"col_stop": 15,
|
||||
"path": "",
|
||||
"content": " x -= 1;"
|
||||
}
|
||||
}
|
||||
},
|
||||
"span": {
|
||||
"line_start": 4,
|
||||
"line_stop": 4,
|
||||
"col_start": 9,
|
||||
"col_stop": 15,
|
||||
"path": "",
|
||||
"content": " x -= 1;"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"span": {
|
||||
"line_start": 3,
|
||||
"line_stop": 5,
|
||||
"col_start": 19,
|
||||
"col_stop": 6,
|
||||
"path": "",
|
||||
"content": " for i in 0..3 {\n...\n }"
|
||||
}
|
||||
},
|
||||
"span": {
|
||||
"line_start": 3,
|
||||
"line_stop": 5,
|
||||
"col_start": 5,
|
||||
"col_stop": 6,
|
||||
"path": "",
|
||||
"content": " for i in 0..3 {\n...\n }"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Console": {
|
||||
"function": {
|
||||
"Assert": {
|
||||
"Binary": {
|
||||
"left": {
|
||||
"Identifier": "{\"name\":\"x\",\"span\":\"{\\\"line_start\\\":6,\\\"line_stop\\\":6,\\\"col_start\\\":20,\\\"col_stop\\\":21,\\\"path\\\":\\\"\\\",\\\"content\\\":\\\" console.assert(x == 7u16);\\\"}\"}"
|
||||
},
|
||||
"right": {
|
||||
"Value": {
|
||||
"Integer": [
|
||||
"U16",
|
||||
"7",
|
||||
{
|
||||
"line_start": 6,
|
||||
"line_stop": 6,
|
||||
"col_start": 25,
|
||||
"col_stop": 29,
|
||||
"path": "",
|
||||
"content": " console.assert(x == 7u16);"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"op": "Eq",
|
||||
"span": {
|
||||
"line_start": 6,
|
||||
"line_stop": 6,
|
||||
"col_start": 20,
|
||||
"col_stop": 29,
|
||||
"path": "",
|
||||
"content": " console.assert(x == 7u16);"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"span": {
|
||||
"line_start": 6,
|
||||
"line_stop": 6,
|
||||
"col_start": 5,
|
||||
"col_stop": 29,
|
||||
"path": "",
|
||||
"content": " console.assert(x == 7u16);"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"span": {
|
||||
"line_start": 1,
|
||||
"line_stop": 7,
|
||||
"col_start": 17,
|
||||
"col_stop": 2,
|
||||
"path": "",
|
||||
"content": "function main() {\n...\n}"
|
||||
}
|
||||
},
|
||||
"span": {
|
||||
"line_start": 1,
|
||||
"line_stop": 7,
|
||||
"col_start": 1,
|
||||
"col_stop": 2,
|
||||
"path": "",
|
||||
"content": "function main() {\n...\n}\n\n\n\n"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
function main() {
|
||||
let x = 10u16;
|
||||
for i in 0..3 {
|
||||
x -= 1;
|
||||
}
|
||||
console.assert(x == 7u16);
|
||||
}
|
@ -1,85 +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::{assert_satisfied, parse_program};
|
||||
#[allow(unused)]
|
||||
use leo_asg::{new_context, Asg, AsgContext};
|
||||
use leo_ast::Ast;
|
||||
use leo_compiler::TypeInferencePhase;
|
||||
use leo_imports::ImportParser;
|
||||
use leo_parser::parser;
|
||||
|
||||
thread_local! {
|
||||
static THREAD_GLOBAL_CONTEXT: AsgContext<'static> = {
|
||||
let leaked = Box::leak(Box::new(leo_asg::new_alloc_context()));
|
||||
leo_asg::new_context(leaked)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn thread_leaked_context() -> AsgContext<'static> {
|
||||
THREAD_GLOBAL_CONTEXT.with(|f| *f)
|
||||
}
|
||||
|
||||
pub fn parse_program_ast(file_string: &str) -> Ast {
|
||||
const TEST_PROGRAM_PATH: &str = "";
|
||||
let test_program_file_path = std::path::PathBuf::from(TEST_PROGRAM_PATH);
|
||||
|
||||
let mut ast = Ast::new(
|
||||
parser::parse(test_program_file_path.to_str().expect("unwrap fail"), &file_string)
|
||||
.expect("Failed to parse file."),
|
||||
);
|
||||
ast.canonicalize().expect("Failed to canonicalize program.");
|
||||
|
||||
let program = ast.clone().into_repr();
|
||||
let asg = Asg::new(thread_leaked_context(), &program, &mut ImportParser::default())
|
||||
.expect("Failed to create ASG from AST");
|
||||
|
||||
let new_ast = TypeInferencePhase::default()
|
||||
.phase_ast(&program, &asg.into_repr())
|
||||
.expect("Failed to produce type inference ast.");
|
||||
|
||||
new_ast
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_basic() {
|
||||
// Check program is valid.
|
||||
let program_string = include_str!("basic.leo");
|
||||
let program = parse_program(program_string).unwrap();
|
||||
assert_satisfied(program);
|
||||
|
||||
// Check we get expected ast.
|
||||
let ast = parse_program_ast(program_string);
|
||||
let expected_json = include_str!("basic.json");
|
||||
let expected_ast: Ast = Ast::from_json_string(expected_json).expect("Unable to parse json.");
|
||||
|
||||
assert_eq!(expected_ast, ast);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_for_loop_and_compound() {
|
||||
// Check program is valid.
|
||||
let program_string = include_str!("for_loop_and_compound.leo");
|
||||
let program = parse_program(program_string).unwrap();
|
||||
assert_satisfied(program);
|
||||
|
||||
// Check we get expected ast.
|
||||
let ast = parse_program_ast(program_string);
|
||||
let expected_json = include_str!("for_loop_and_compound.json");
|
||||
let expected_ast: Ast = Ast::from_json_string(expected_json).expect("Unable to parse json.");
|
||||
|
||||
assert_eq!(expected_ast, ast);
|
||||
}
|
@ -25,9 +25,7 @@ that we suggest few changes to Leo CLI and Manifest:
|
||||
- allow custom names for imports to manually resolve name conflicts;
|
||||
- add "curve" and "proving system" sections to the Manifest;
|
||||
- add "include" and "exclude" parameters for "proving system" and "curve";
|
||||
|
||||
Later this solution can be improved by adding a lock-file which would lock
|
||||
imported packages based on both their contents and version.
|
||||
- add a lock file which would store imported dependencies and their relations;
|
||||
|
||||
# Motivation
|
||||
|
||||
@ -109,12 +107,7 @@ To support updated Manifest new command should be added to Leo CLI.
|
||||
|
||||
```bash
|
||||
# pull imports
|
||||
leo install
|
||||
```
|
||||
|
||||
Alternatively it can be called `pull`.
|
||||
```
|
||||
leo pull
|
||||
leo fetch
|
||||
```
|
||||
|
||||
## Imports Restructurization
|
||||
@ -155,6 +148,44 @@ first-program => author1-program@0.1.0
|
||||
second-program => author2-program2@1.0.4
|
||||
```
|
||||
|
||||
## Leo.lock
|
||||
|
||||
For imports map to be generated and read by the Leo binary and then by the Leo compiler,
|
||||
a lock file needs to be created. Lock file should be generated by the `leo fetch` command,
|
||||
which will pull the dependencies, process their manifests, and put the required information
|
||||
to the file in the root directory of the program called `Leo.lock`.
|
||||
|
||||
Suggested structure of this file is similar to the Cargo.lock file:
|
||||
|
||||
```
|
||||
[[package]]
|
||||
name = "suit-mk2"
|
||||
version = "0.2.0"
|
||||
author = "ironman"
|
||||
import_name = "suit-mk2"
|
||||
|
||||
[package.dependencies]
|
||||
garbage = "ironman-suit@0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "suit"
|
||||
version = "0.1.0"
|
||||
author = "ironman"
|
||||
import_name = "garbage"
|
||||
```
|
||||
|
||||
In the example above, you can see that all program dependencies are defined as an
|
||||
array called `package`. Each of the dependencies contains main information about
|
||||
it, including the `import_name` field which is the imported package's name in
|
||||
the Leo program. Also, it stores relationships between these dependencies in the
|
||||
field `dependencies`.
|
||||
|
||||
The format described here allows the Leo binary to form an imports map which can be
|
||||
passed to the compiler.
|
||||
|
||||
It is important to note that Leo.lock file is created only when a package has dependencies.
|
||||
For programs with no dependencies, a lock file is not required and not created.
|
||||
|
||||
## Recursive Dependencies
|
||||
|
||||
This improvement introduces recursive dependencies. To solve this case preemptively
|
||||
|
@ -94,6 +94,26 @@ for i in 0..5 {}
|
||||
for i in 0..=5 {}
|
||||
```
|
||||
|
||||
## Step and Direction
|
||||
|
||||
We remark that the step of both counting-up and counting-down loops is implicitly 1;
|
||||
that is, the loop variable is incremented or decremented by 1.
|
||||
|
||||
Whether the loop counts up or down is determined by how the starting and ending bounds compare.
|
||||
Note that the bounds are not necessarily literals;
|
||||
they may be more complex `const` expressions, and thus in general their values are resolved at code flattening time.
|
||||
Because of the type restrictions on bounds, their values are always non-negative integers.
|
||||
If `S` is the integer value of the starting bound and `E` is the integer value of the ending bound,
|
||||
there are several cases to consider:
|
||||
1. If `S == E` and the ending bound is exclusive, there is no actual loop; the range is empty.
|
||||
2. If `S == E` and the ending bound is inclusive, the loop consists of just one iteration; the loop counts neither up nor down.
|
||||
3. If `S < E` and the ending bound is exclusive, the loop counts up, from `S` to `E-1`.
|
||||
4. If `S < E` and the ending bound is inclusive, the loop counts up, from `S` to `E`.
|
||||
5. If `S > E` and the ending bound is exclusive, the loop counts down, from `S` to `E+1`.
|
||||
6. If `S > E` and the ending bound is inclusive, the loop counts down, from `S` to `E`.
|
||||
|
||||
Cases 3 and 5 consist of one or more iterations; cases 4 and 6 consist of two or more iterations.
|
||||
|
||||
## Example
|
||||
|
||||
The code example demostrated in the Motivation part of this document
|
||||
|
3
grammar/.gitattributes
vendored
3
grammar/.gitattributes
vendored
@ -1 +1,2 @@
|
||||
abnf-grammar.txt text eol=crlf
|
||||
abnf-grammar.txt text eol=crlf
|
||||
format-abnf-grammar.txt text eol=crlf
|
BIN
grammar/FORMAT_ABNF_GRAMMER.md
Normal file
BIN
grammar/FORMAT_ABNF_GRAMMER.md
Normal file
Binary file not shown.
Binary file not shown.
@ -555,11 +555,8 @@ unicode-character-escape = %s"\u{" 1*6hexadecimal-digit "}"
|
||||
; A string literal consists of one or more elements surrounded by double quotes.
|
||||
; Each element is any character other than double quote or backslash,
|
||||
; or an escape among the same ones used for elements of character literals.
|
||||
; There must be at least one element
|
||||
; because string literals denote character arrays,
|
||||
; and arrays must not be empty.
|
||||
|
||||
string-literal = double-quote 1*string-literal-element double-quote
|
||||
string-literal = double-quote *string-literal-element double-quote
|
||||
|
||||
string-literal-element = not-double-quote-or-backslash
|
||||
/ simple-character-escape
|
||||
|
50
grammar/format-abnf-grammar.txt
Normal file
50
grammar/format-abnf-grammar.txt
Normal file
@ -0,0 +1,50 @@
|
||||
; 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/>.
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
; Background on ABNF
|
||||
; ------------------
|
||||
|
||||
; ABNF is an Internet standard:
|
||||
; for more info please checkout the
|
||||
; [README](./README.md) in this directory.
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
; Format String
|
||||
; -------------------
|
||||
|
||||
; This ABNF grammar consists of one grammar:
|
||||
; that describes how a Leo string-literal is parsed
|
||||
; for formatting. Meaning in this context
|
||||
; all characters are already parsed and we don't
|
||||
; have to worry about escapes or etc.
|
||||
|
||||
not-brace = %x0-7A / %x7C / %x7E-10FFFF ; anything but { or }
|
||||
|
||||
format-string-container = "{}"
|
||||
|
||||
format-string-open-brace = "{{"
|
||||
|
||||
format-string-close-brace = "}}"
|
||||
|
||||
format-string-element = not-brace
|
||||
/ format-string-container
|
||||
/ format-string-open-brace
|
||||
/ format-string-close-brace
|
||||
|
||||
format-string = *format-string-element
|
@ -40,7 +40,7 @@
|
||||
//
|
||||
|
||||
use abnf::types::{Node, Rule};
|
||||
use anyhow::Result;
|
||||
use anyhow::{anyhow, Result};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
/// Processor's scope. Used when code block or definition starts or ends.
|
||||
@ -197,18 +197,24 @@ fn parse_abnf_node(node: &Node, sum: &mut Vec<String>) {
|
||||
|
||||
fn main() -> Result<()> {
|
||||
// Take Leo ABNF grammar file.
|
||||
let grammar = include_str!("../abnf-grammar.txt");
|
||||
let args: Vec<String> = std::env::args().collect();
|
||||
let abnf_path = if let Some(path) = args.get(1) {
|
||||
std::path::Path::new(path)
|
||||
} else {
|
||||
return Err(anyhow!("Usage Error: expects one argument to abnf file to convert."));
|
||||
};
|
||||
let grammar = std::fs::read_to_string(abnf_path)?;
|
||||
|
||||
// Parse ABNF to get list of all definitions.
|
||||
// Rust ABNF does not provide support for `%s` (case sensitive strings, part of
|
||||
// the standard); so we need to remove all occurrences before parsing.
|
||||
let parsed = abnf::rulelist(&str::replace(grammar, "%s", "")).map_err(|e| {
|
||||
let parsed = abnf::rulelist(&str::replace(&grammar, "%s", "")).map_err(|e| {
|
||||
eprintln!("{}", &e);
|
||||
anyhow::anyhow!(e)
|
||||
})?;
|
||||
|
||||
// Init parser and run it. That's it.
|
||||
let mut parser = Processor::new(grammar, parsed);
|
||||
let mut parser = Processor::new(&grammar, parsed);
|
||||
parser.process();
|
||||
|
||||
// Print result of conversion to STDOUT.
|
||||
|
@ -18,8 +18,8 @@ use crate::{commands::Command, context::Context};
|
||||
use leo_compiler::{
|
||||
compiler::{thread_leaked_context, Compiler},
|
||||
group::targets::edwards_bls12::EdwardsGroupType,
|
||||
AstSnapshotOptions,
|
||||
CompilerOptions,
|
||||
TheoremOptions,
|
||||
};
|
||||
use leo_package::{
|
||||
inputs::*,
|
||||
@ -46,14 +46,14 @@ pub struct BuildOptions {
|
||||
pub disable_code_elimination: bool,
|
||||
#[structopt(long, help = "Disable all compiler optimizations")]
|
||||
pub disable_all_optimizations: bool,
|
||||
#[structopt(long, help = "Writes all theorem input AST files.")]
|
||||
pub enable_all_theorems: bool,
|
||||
#[structopt(long, help = "Writes AST files needed for the initial theorem before any changes.")]
|
||||
pub enable_initial_theorem: bool,
|
||||
#[structopt(long, help = "Writes AST files needed for canonicalization theorem.")]
|
||||
pub enable_canonicalized_theorem: bool,
|
||||
#[structopt(long, help = "Writes AST files needed for type inference theorem.")]
|
||||
pub enable_type_inferenced_theorem: bool,
|
||||
#[structopt(long, help = "Writes all AST snapshots for the different compiler phases.")]
|
||||
pub enable_all_ast_snapshots: bool,
|
||||
#[structopt(long, help = "Writes AST snapshot of the initial parse.")]
|
||||
pub enable_initial_ast_snapshot: bool,
|
||||
#[structopt(long, help = "Writes AST snapshot after the canonicalization phase.")]
|
||||
pub enable_canonicalized_ast_snapshot: bool,
|
||||
#[structopt(long, help = "Writes AST snapshot after the type inference phase.")]
|
||||
pub enable_type_inferenced_ast_snapshot: bool,
|
||||
}
|
||||
|
||||
impl Default for BuildOptions {
|
||||
@ -63,10 +63,10 @@ impl Default for BuildOptions {
|
||||
disable_constant_folding: true,
|
||||
disable_code_elimination: true,
|
||||
disable_all_optimizations: true,
|
||||
enable_all_theorems: false,
|
||||
enable_initial_theorem: false,
|
||||
enable_canonicalized_theorem: false,
|
||||
enable_type_inferenced_theorem: false,
|
||||
enable_all_ast_snapshots: false,
|
||||
enable_initial_ast_snapshot: false,
|
||||
enable_canonicalized_ast_snapshot: false,
|
||||
enable_type_inferenced_ast_snapshot: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -89,19 +89,19 @@ impl From<BuildOptions> for CompilerOptions {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<BuildOptions> for TheoremOptions {
|
||||
impl From<BuildOptions> for AstSnapshotOptions {
|
||||
fn from(options: BuildOptions) -> Self {
|
||||
if options.enable_all_theorems {
|
||||
TheoremOptions {
|
||||
if options.enable_all_ast_snapshots {
|
||||
AstSnapshotOptions {
|
||||
initial: true,
|
||||
canonicalized: true,
|
||||
type_inferenced: true,
|
||||
}
|
||||
} else {
|
||||
TheoremOptions {
|
||||
initial: options.enable_initial_theorem,
|
||||
canonicalized: options.enable_canonicalized_theorem,
|
||||
type_inferenced: options.enable_type_inferenced_theorem,
|
||||
AstSnapshotOptions {
|
||||
initial: options.enable_initial_ast_snapshot,
|
||||
canonicalized: options.enable_canonicalized_ast_snapshot,
|
||||
type_inferenced: options.enable_type_inferenced_ast_snapshot,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -174,7 +174,7 @@ impl Command for Build {
|
||||
// Log compilation of files to console
|
||||
tracing::info!("Compiling main program... ({:?})", main_file_path);
|
||||
|
||||
if self.compiler_options.disable_canonicalization && self.compiler_options.enable_canonicalized_theorem {
|
||||
if self.compiler_options.disable_canonicalization && self.compiler_options.enable_canonicalized_ast_snapshot {
|
||||
tracing::warn!(
|
||||
"Can not ask for canonicalization theorem without having canonicalization compiler feature enabled."
|
||||
);
|
||||
@ -197,8 +197,8 @@ impl Command for Build {
|
||||
&state_path,
|
||||
thread_leaked_context(),
|
||||
Some(self.compiler_options.clone().into()),
|
||||
Some(self.compiler_options.into()),
|
||||
imports_map,
|
||||
Some(self.compiler_options.into()),
|
||||
)?;
|
||||
|
||||
// Compute the current program checksum
|
||||
|
@ -112,8 +112,8 @@ impl Command for Test {
|
||||
output_directory.clone(),
|
||||
thread_leaked_context(),
|
||||
Some(self.compiler_options.clone().into()),
|
||||
Some(self.compiler_options.clone().into()),
|
||||
std::collections::HashMap::new(),
|
||||
Some(self.compiler_options.clone().into()),
|
||||
)?;
|
||||
|
||||
let temporary_program = program;
|
||||
|
124
parser/README.md
Normal file
124
parser/README.md
Normal file
@ -0,0 +1,124 @@
|
||||
# Leo Parser
|
||||
[![Crates.io](https://img.shields.io/crates/v/leo-parser.svg?color=neon)](https://crates.io/crates/leo-parser)
|
||||
[![Authors](https://img.shields.io/badge/authors-Aleo-orange.svg)](../AUTHORS)
|
||||
[![License](https://img.shields.io/badge/License-GPLv3-blue.svg)](./LICENSE.md)
|
||||
|
||||
This directory contains the code to tokenize, lex and parse Leo files to the [Leo AST](./../ast/README.md).
|
||||
|
||||
## Tokenizer
|
||||
|
||||
The tokenizer contains all tokens in Leo.
|
||||
It also decides which tokens are keywords.
|
||||
Meaning that keywords are a subset of tokens.
|
||||
The lexer goes through character by character as bytes, and converts the bytes into the tokens.
|
||||
|
||||
### Tokens
|
||||
|
||||
Bolded ones are also keywords.
|
||||
|
||||
#### Literals
|
||||
- CommentLine
|
||||
- CommentBlock
|
||||
- StringLit
|
||||
- Ident
|
||||
- Int
|
||||
- **True**
|
||||
- **False**
|
||||
- AddressLit
|
||||
- CharLit
|
||||
|
||||
#### Symbols
|
||||
- At
|
||||
- Not
|
||||
- And
|
||||
- Or
|
||||
- Eq
|
||||
- NotEq
|
||||
- Lt
|
||||
- LtEq
|
||||
- Gt
|
||||
- GtEq
|
||||
- Add
|
||||
- Minus
|
||||
- Mul
|
||||
- Div
|
||||
- Exp
|
||||
- Assign
|
||||
- AddEq
|
||||
- MinusEq
|
||||
- MulEq
|
||||
- DivEq
|
||||
- ExpEq
|
||||
- LeftParen
|
||||
- RightParen
|
||||
- LeftSquare
|
||||
- RightSquare
|
||||
- LeftCurly
|
||||
- RightCurly
|
||||
- Comma
|
||||
- Dot
|
||||
- DotDot
|
||||
- DotDotDot
|
||||
- Semicolon
|
||||
- Colon
|
||||
- DoubleColon
|
||||
- Question
|
||||
- Arrow
|
||||
- Underscore
|
||||
|
||||
#### Types
|
||||
- **U8**
|
||||
- **U16**
|
||||
- **U32**
|
||||
- **U64**
|
||||
- **U128**
|
||||
- **I8**
|
||||
- **I16**
|
||||
- **I32**
|
||||
- **I64**
|
||||
- **I128**
|
||||
- **Field**
|
||||
- **Group**
|
||||
- **Bool**
|
||||
- **Address**
|
||||
- **Char**
|
||||
- **BigSelf**
|
||||
|
||||
#### Words
|
||||
- **Input**
|
||||
- **LittleSelf**
|
||||
- **Import**
|
||||
- **As**
|
||||
- **Circuit**
|
||||
- **Console**
|
||||
- **Const**
|
||||
- **Else**
|
||||
- **For**
|
||||
- **Function**
|
||||
- **If**
|
||||
- **In**
|
||||
- **Let**
|
||||
- **Mut**
|
||||
- **Return**
|
||||
- **Static**
|
||||
- **String**
|
||||
|
||||
#### Meta
|
||||
- Eof
|
||||
|
||||
## Parser
|
||||
|
||||
The parser converts the tokens to the [Leo AST](./../ast/README.md).
|
||||
|
||||
The parser is broken down to different files that correspond to different aspects of the AST:
|
||||
|
||||
- [File](./src/parser/file.rs) - Parses the top level nodes in Leo.
|
||||
- [Types](./src/parser/type_.rs) - Parses the type declarations in Leo.
|
||||
- [Statements](./src/parser/statement.rs) - Parses the different kinds of statements.
|
||||
- [Expressions](./src/parser/expression.rs) - Parses the different kinds of expressions.
|
||||
|
||||
For more information on those please read the Leo AST README, linked above.
|
||||
|
||||
## Grammar Relation
|
||||
|
||||
All function and token names are as close as possible to the [Leo Grammar](./../grammar/README.md)
|
@ -232,9 +232,9 @@ impl ParserContext {
|
||||
}
|
||||
|
||||
///
|
||||
/// Returns a [`FormatString`] AST node if the next tokens represent a formatted string.
|
||||
/// Returns a [`ConsoleArgs`] AST node if the next tokens represent a formatted string.
|
||||
///
|
||||
pub fn parse_formatted_string(&mut self) -> SyntaxResult<FormatString> {
|
||||
pub fn parse_console_args(&mut self) -> SyntaxResult<ConsoleArgs> {
|
||||
let start_span;
|
||||
let string = match self.expect_any()? {
|
||||
SpannedToken {
|
||||
@ -247,7 +247,7 @@ impl ParserContext {
|
||||
SpannedToken { token, span } => return Err(SyntaxError::unexpected_str(&token, "formatted string", &span)),
|
||||
};
|
||||
|
||||
let parts = FormatStringPart::from_string(string);
|
||||
// let parts = FormatStringPart::from_string(string);
|
||||
|
||||
let mut parameters = Vec::new();
|
||||
while self.eat(Token::Comma).is_some() {
|
||||
@ -255,8 +255,8 @@ impl ParserContext {
|
||||
parameters.push(param);
|
||||
}
|
||||
|
||||
Ok(FormatString {
|
||||
parts,
|
||||
Ok(ConsoleArgs {
|
||||
string,
|
||||
span: &start_span + parameters.last().map(|x| x.span()).unwrap_or(&start_span),
|
||||
parameters,
|
||||
})
|
||||
@ -275,9 +275,9 @@ impl ParserContext {
|
||||
let expr = self.parse_expression()?;
|
||||
ConsoleFunction::Assert(expr)
|
||||
}
|
||||
"debug" => ConsoleFunction::Debug(self.parse_formatted_string()?),
|
||||
"error" => ConsoleFunction::Error(self.parse_formatted_string()?),
|
||||
"log" => ConsoleFunction::Log(self.parse_formatted_string()?),
|
||||
"debug" => ConsoleFunction::Debug(self.parse_console_args()?),
|
||||
"error" => ConsoleFunction::Error(self.parse_console_args()?),
|
||||
"log" => ConsoleFunction::Log(self.parse_console_args()?),
|
||||
x => {
|
||||
return Err(SyntaxError::unexpected_ident(
|
||||
&x,
|
||||
|
@ -280,7 +280,7 @@ impl Token {
|
||||
}
|
||||
}
|
||||
|
||||
if i == input.len() || i == 1 || !end {
|
||||
if i == input.len() || !end {
|
||||
return (0, None);
|
||||
}
|
||||
|
||||
|
@ -58,9 +58,8 @@ pub enum Token {
|
||||
AddressLit(#[serde(with = "leo_ast::common::tendril_json")] StrTendril),
|
||||
CharLit(Char),
|
||||
|
||||
At,
|
||||
|
||||
// Symbols
|
||||
At,
|
||||
Not,
|
||||
And,
|
||||
Or,
|
||||
|
12
tests/compiler/array/array_range_access_fail.leo
Normal file
12
tests/compiler/array/array_range_access_fail.leo
Normal file
@ -0,0 +1,12 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
input_file: input/array_range_access_fail.in
|
||||
*/
|
||||
|
||||
function main (
|
||||
const x: u32
|
||||
) {
|
||||
const y = [1u8; 3];
|
||||
const z: [u8; 2] = y[..1u32][..x];
|
||||
}
|
9
tests/compiler/array/array_size_zero_fail.leo
Normal file
9
tests/compiler/array/array_size_zero_fail.leo
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
input_file: input/dummy.in
|
||||
*/
|
||||
|
||||
function main() {
|
||||
let a = [true; (0)];
|
||||
}
|
2
tests/compiler/array/input/array_range_access_fail.in
Normal file
2
tests/compiler/array/input/array_range_access_fail.in
Normal file
@ -0,0 +1,2 @@
|
||||
[constants]
|
||||
x: u32 = 1u32;
|
27
tests/compiler/circuits/big_self_in_circuit_replacement.leo
Normal file
27
tests/compiler/circuits/big_self_in_circuit_replacement.leo
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: input/dummy.in
|
||||
*/
|
||||
|
||||
circuit Foo {
|
||||
x: u32;
|
||||
|
||||
function new() -> Self {
|
||||
let new: Self = Self {
|
||||
x: 1u32
|
||||
};
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
function etc() {
|
||||
let y = [0u32, 1, 2, 3];
|
||||
y[Self {x: 0}.x] += 2;
|
||||
}
|
||||
}
|
||||
|
||||
function main(y: bool) -> bool {
|
||||
let foo: Foo = Foo::new();
|
||||
return foo.x == 1u32 && y;
|
||||
}
|
@ -1,3 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
input_file: input/dummy.in
|
||||
*/
|
||||
|
||||
circuit Foo {
|
||||
x: u32;
|
||||
|
@ -1,3 +1,9 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/dummy.in
|
||||
*/
|
||||
|
||||
circuit Foo {
|
||||
f: u8;
|
||||
y: (u8, u8);
|
||||
@ -7,37 +13,33 @@ circuit Foo {
|
||||
return 1u16;
|
||||
}
|
||||
}
|
||||
function main() {
|
||||
|
||||
function main(k: bool) -> bool {
|
||||
let x = 10u32;
|
||||
x += 20;
|
||||
console.assert(x == 30u32);
|
||||
|
||||
let w = 3u32;
|
||||
w += x;
|
||||
console.assert(w == 33u32);
|
||||
|
||||
let y = [1u8, 2u8, 3, 4];
|
||||
y[0] += 3u8;
|
||||
y[0..3][1] *= 3;
|
||||
console.assert(y[0] == 4u8);
|
||||
console.assert(y[1] == 6u8);
|
||||
|
||||
let z = (1u8, 2u8);
|
||||
z.1 += 3u8;
|
||||
console.assert(z.1 == 5u8);
|
||||
|
||||
let foo = Foo { f: 6u8, y: (1u8, 1u8) };
|
||||
foo.f += 2u8;
|
||||
console.assert(foo.f == 8u8);
|
||||
|
||||
let complex = 2u8;
|
||||
complex += 22u8 - 2u8+ 1u8;
|
||||
console.assert(complex == 23u8);
|
||||
let a = [[0u8; 1]; 4];
|
||||
a[2][0] += 1u8;
|
||||
console.assert(a[2][0] == 1u8);
|
||||
|
||||
let b = [0u8; (4, 1)];
|
||||
b[2][0] += 1u8;
|
||||
console.assert(a[2][0] == 1u8);
|
||||
|
||||
return x == 30u32 && w == 33u32 && y[0] == 4u8 && y[1] == 6u8
|
||||
&& z.1 == 5u8 && foo.f == 8u8 && a[2][0] == 1u8 && a[2][0] == 1u8
|
||||
&& k;
|
||||
}
|
5
tests/compiler/statements/inputs/dummy.in
Normal file
5
tests/compiler/statements/inputs/dummy.in
Normal file
@ -0,0 +1,5 @@
|
||||
[main]
|
||||
k: bool = true;
|
||||
|
||||
[registers]
|
||||
r0: bool = true;
|
5
tests/compiler/string/inputs/two.in
Normal file
5
tests/compiler/string/inputs/two.in
Normal file
@ -0,0 +1,5 @@
|
||||
[main]
|
||||
s2: [char; 2] = "he";
|
||||
|
||||
[registers]
|
||||
out: bool = true;
|
14
tests/compiler/string/string_transformation.leo
Normal file
14
tests/compiler/string/string_transformation.leo
Normal file
@ -0,0 +1,14 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
input_file: inputs/two.in
|
||||
*/
|
||||
|
||||
function main(s2: [char; 2]) -> bool {
|
||||
let s = "\u{2764}ello, World!\u{DDDD}";
|
||||
s[..2] = s2;
|
||||
let x = "test1";
|
||||
let z = [1u8, 2u8, 3u8, 4u8];
|
||||
z[0.."test" == "test" ? 2 : 2] = [10u8, 10];
|
||||
return z == [10u8, 10, 3, 4] && s == "hello, World!\u{DDDD}";
|
||||
}
|
@ -22,3 +22,6 @@ outputs:
|
||||
a:
|
||||
type: bool
|
||||
value: "false"
|
||||
initial_ast: 1b4069c1fe2f0b258116c5864b19dfb2205e3cd8e13ea79d78fcdb0e9c1a8d50
|
||||
canonicalized_ast: 1b4069c1fe2f0b258116c5864b19dfb2205e3cd8e13ea79d78fcdb0e9c1a8d50
|
||||
type_inferenced_ast: d2aefbdd9fd4c931d4ee60f1a435f3da0d827e7425d2fd0a9868de22cc11ed73
|
||||
|
@ -22,3 +22,6 @@ outputs:
|
||||
a:
|
||||
type: bool
|
||||
value: "false"
|
||||
initial_ast: 975c6893ed20b632a3dc9c39f7fe9f381e7dda4b17b6c1f05ff7480e3bf2ee9d
|
||||
canonicalized_ast: 975c6893ed20b632a3dc9c39f7fe9f381e7dda4b17b6c1f05ff7480e3bf2ee9d
|
||||
type_inferenced_ast: bbc3818f0267a746d6ab324ef9b9de489ca65cd1624f528dae941841f39517af
|
||||
|
@ -0,0 +1,5 @@
|
||||
---
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- " --> compiler-test:7:24\n |\n 7 | const z: [u8; 2] = y[..1u32][..x];\n | ^^^^^^^^^^^^^^\n |\n = array index out of bounds: '0'"
|
@ -0,0 +1,5 @@
|
||||
---
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- " --> compiler-test:4:13\n |\n 4 | let a = [true; (0)];\n | ^^^^^^^^^^^\n |\n = received dimension size of 0, expected it to be 1 or larger."
|
@ -16,3 +16,6 @@ outputs:
|
||||
out:
|
||||
type: bool
|
||||
value: "true"
|
||||
initial_ast: 9808de8c342c41e060d3d3134eb168c8d8cc3ff0641cb8d9779a1746b9fa1687
|
||||
canonicalized_ast: 1479a9afd623ad11ca137555fd86a3f0a6da39641d5b2da712273242541c246e
|
||||
type_inferenced_ast: 9bf998e088b9cce0f40a0326fa8e744c88d8168e04c563a2fbd6a57acd23da1f
|
||||
|
@ -22,3 +22,6 @@ outputs:
|
||||
x:
|
||||
type: bool
|
||||
value: "false"
|
||||
initial_ast: 25f4af112eb1512952d78bb7fa1d5287e3ab778255307f69304bbe1756575085
|
||||
canonicalized_ast: 248b7cc7462c3f035f337c9232a08bb5a911d7f4e153dd804a32bc597adb0210
|
||||
type_inferenced_ast: ebc3a5632c2d65e51cd9934b1ee4e395867808deeda3ecddfeaebb1b08093ed7
|
||||
|
@ -22,3 +22,6 @@ outputs:
|
||||
x:
|
||||
type: bool
|
||||
value: "true"
|
||||
initial_ast: b3bae883863f88babaafa80d4c029974767fba5fea89ac8c2ab10512e61a38ba
|
||||
canonicalized_ast: 9070de3276acf8d06ac58439247130e444c9b02de25b968ad1fc746650a1896c
|
||||
type_inferenced_ast: 40a38002031be2cf0141c9ea33562fe69fc3891baeba9c92c487915b97d82507
|
||||
|
@ -16,3 +16,6 @@ outputs:
|
||||
x:
|
||||
type: bool
|
||||
value: "true"
|
||||
initial_ast: f5e4014d45239734a04d57c7b130fdf9752de245a4341062063aa5e818c5aa05
|
||||
canonicalized_ast: 8c16a6b011fc067411acaa497386bc5df9b96b91ef739f4992ba416ecf98bafc
|
||||
type_inferenced_ast: 17d810699ef381a0a9c4efcd2ad6da64b76ce5d629c05db7b2d07d563e077548
|
||||
|
@ -16,3 +16,6 @@ outputs:
|
||||
x:
|
||||
type: bool
|
||||
value: "true"
|
||||
initial_ast: 25f4af112eb1512952d78bb7fa1d5287e3ab778255307f69304bbe1756575085
|
||||
canonicalized_ast: 248b7cc7462c3f035f337c9232a08bb5a911d7f4e153dd804a32bc597adb0210
|
||||
type_inferenced_ast: ebc3a5632c2d65e51cd9934b1ee4e395867808deeda3ecddfeaebb1b08093ed7
|
||||
|
@ -16,3 +16,6 @@ outputs:
|
||||
r0:
|
||||
type: bool
|
||||
value: "true"
|
||||
initial_ast: 21f90ee0a01e1238101360b72909766a148155d853fd903a3031d66340915101
|
||||
canonicalized_ast: cccb2040ce9b654f27e9a8e36976f220545c2888ed2aa9db73843b38407322f2
|
||||
type_inferenced_ast: 7cee4f94edf86b6c61af5dbb389b8901c57292810abf4cd6b4855dfee40370c7
|
||||
|
@ -16,3 +16,6 @@ outputs:
|
||||
r0:
|
||||
type: bool
|
||||
value: "true"
|
||||
initial_ast: 796cfe23085a2fd72700df353d266d3e2f62e893faeba8ed1af5ee5178f8e706
|
||||
canonicalized_ast: d06970075b65456a138d9286fd3c445c928a55bf9819d98603b494c38563eae1
|
||||
type_inferenced_ast: 41b1e49c972a34ed3d4629feabe3cb37f2078ba44fd1f3bee0a1888ca86f7ae4
|
||||
|
@ -16,3 +16,6 @@ outputs:
|
||||
r0:
|
||||
type: bool
|
||||
value: "true"
|
||||
initial_ast: 3c24983a1b881bd00f5f0fd3a40b471a35f5252798f4ed81784b68693529ad59
|
||||
canonicalized_ast: 177d06133dcc527a3110335158a888f4a0e5a5e904c2d6df57807563fd0ab386
|
||||
type_inferenced_ast: 06e32299c26e20b9a25104686911ecd4e94123bd8a90e7890a244b6288678f27
|
||||
|
@ -22,3 +22,6 @@ outputs:
|
||||
r:
|
||||
type: "[u8; 3]"
|
||||
value: "\"123\""
|
||||
initial_ast: 81dd2c459d5a1bff4963fb2cfdc67348183061934025b96739dc05c7b65a2a8b
|
||||
canonicalized_ast: 81dd2c459d5a1bff4963fb2cfdc67348183061934025b96739dc05c7b65a2a8b
|
||||
type_inferenced_ast: fcb8de69c92dff4a4adb8a160fc3b78042f394cd0dc627c5bf06820a095d7012
|
||||
|
@ -16,3 +16,6 @@ outputs:
|
||||
x:
|
||||
type: bool
|
||||
value: "true"
|
||||
initial_ast: ca5fc7bf19d8e6ee1b1421f1a37ea84c42bc89e8ac90711488bc17e996e88a91
|
||||
canonicalized_ast: ca5fc7bf19d8e6ee1b1421f1a37ea84c42bc89e8ac90711488bc17e996e88a91
|
||||
type_inferenced_ast: 2823901914ffea0d4cfcf449b9e45b46f67255e0b50f7a946b0552b240bedc0d
|
||||
|
@ -16,3 +16,6 @@ outputs:
|
||||
r0:
|
||||
type: bool
|
||||
value: "true"
|
||||
initial_ast: a588964cfb6989b22b8bf7d6feaf90d09e228d61b09a48fd4e5e4b44473b5bd0
|
||||
canonicalized_ast: a588964cfb6989b22b8bf7d6feaf90d09e228d61b09a48fd4e5e4b44473b5bd0
|
||||
type_inferenced_ast: 838744e4d681a06ccb685d0c0de65897234d64f0a49887e896fbda087f3edfd6
|
||||
|
@ -16,3 +16,6 @@ outputs:
|
||||
x:
|
||||
type: bool
|
||||
value: "true"
|
||||
initial_ast: 2506cc8885eaae80a2ff90d1d231440dcfafd10fd8eb53317112ff2d2240d65e
|
||||
canonicalized_ast: 2506cc8885eaae80a2ff90d1d231440dcfafd10fd8eb53317112ff2d2240d65e
|
||||
type_inferenced_ast: bc0e1e40fcb7ac04e1dec943be5b93a1e39d43bee68a26713716765775674577
|
||||
|
@ -16,3 +16,6 @@ outputs:
|
||||
x:
|
||||
type: bool
|
||||
value: "true"
|
||||
initial_ast: e238db049bc888e9243b421a188edbe5ae160127164b6bb75e54125052455565
|
||||
canonicalized_ast: e238db049bc888e9243b421a188edbe5ae160127164b6bb75e54125052455565
|
||||
type_inferenced_ast: e498240b5cb8c4d46a0b1035f208025df8e5feeabf9dddaa859a0a695ae8c5f6
|
||||
|
@ -16,3 +16,6 @@ outputs:
|
||||
r0:
|
||||
type: bool
|
||||
value: "true"
|
||||
initial_ast: d6195e7c9e70c521660ba312c607850110d864a1979004972a0f2908d476efd3
|
||||
canonicalized_ast: a3483e0912a5d47c95775b1b2d2c62fa5acd5f3c0432757dc261475183156490
|
||||
type_inferenced_ast: 54b0f61496c50ced01700f61d9c3eac6056d3835f38c2f39fe0c20e45447be63
|
||||
|
@ -16,3 +16,6 @@ outputs:
|
||||
x:
|
||||
type: bool
|
||||
value: "true"
|
||||
initial_ast: 42d14deb7baaf81b59723a453b1aa09e68bfc8677ce2903596de69ad6b7677ab
|
||||
canonicalized_ast: 42d14deb7baaf81b59723a453b1aa09e68bfc8677ce2903596de69ad6b7677ab
|
||||
type_inferenced_ast: 1559a3a4db454285ab969d20276d9112fca0b24f6726f64d4b0371dccde32abf
|
||||
|
@ -16,3 +16,6 @@ outputs:
|
||||
x:
|
||||
type: bool
|
||||
value: "true"
|
||||
initial_ast: c7cf923f9ca2a963279a8ff7ae9aa0a11eaddc8ba3e107d48f3aef1d1c55a50f
|
||||
canonicalized_ast: c7cf923f9ca2a963279a8ff7ae9aa0a11eaddc8ba3e107d48f3aef1d1c55a50f
|
||||
type_inferenced_ast: 58b19d80de0abea85877257b60305e1f7b9d2e67044f60d0159699131d4ba6ec
|
||||
|
@ -16,3 +16,6 @@ outputs:
|
||||
x:
|
||||
type: bool
|
||||
value: "true"
|
||||
initial_ast: dbc983cae35c2cd763e9bc4505a2d1e6c063fa62ccdc858a75644175512c1558
|
||||
canonicalized_ast: dbc983cae35c2cd763e9bc4505a2d1e6c063fa62ccdc858a75644175512c1558
|
||||
type_inferenced_ast: 42686f9d46c46c829259d4b68643d144d126e61a899e3c413ea09d0ed12d24d1
|
||||
|
@ -16,3 +16,6 @@ outputs:
|
||||
r0:
|
||||
type: bool
|
||||
value: "true"
|
||||
initial_ast: 42a9307b4efda61137f9816a43e5c07a9d6b143bd88f609be7e549cb3b21d731
|
||||
canonicalized_ast: 42a9307b4efda61137f9816a43e5c07a9d6b143bd88f609be7e549cb3b21d731
|
||||
type_inferenced_ast: 67e643a53bb3efb99367869a1f3a937570f61658b004a4261e87b028f4976fad
|
||||
|
@ -16,3 +16,6 @@ outputs:
|
||||
r0:
|
||||
type: bool
|
||||
value: "true"
|
||||
initial_ast: 073b0033613b8c2f8ca027d0486697b5503943dbc65cec9cbbc6b5665e7432e4
|
||||
canonicalized_ast: 6751d75a95af032784678411bb4e0f59b509ec624daea475cab10b9cf14fe6a0
|
||||
type_inferenced_ast: 9b9ac4ba4533ecae7ec74da2ab929cfa85be393391887e95ffadf4d1df3004be
|
||||
|
@ -16,3 +16,6 @@ outputs:
|
||||
r0:
|
||||
type: bool
|
||||
value: "true"
|
||||
initial_ast: d04220b24fd2648e859fab4caf69727b5532dbe1ee68db9d569153514e161a85
|
||||
canonicalized_ast: 36d30f97ff15f08a4a88b384a362168014d56bc90d6a3837fd213b2acfc42357
|
||||
type_inferenced_ast: 363bdf0ef5cf40b1b63a2cefa3d509ca731809568b7392899cbe73ec13104ecd
|
||||
|
@ -16,3 +16,6 @@ outputs:
|
||||
r0:
|
||||
type: bool
|
||||
value: "true"
|
||||
initial_ast: 15fa7dd3949e323b759a7290ff433fb0f6ec83308b1b9b1a6bb129650191bc80
|
||||
canonicalized_ast: 6a0262a7865ecf453b147449c52f23a1ffb38995c45d0a7c23a78255b9cbbb1b
|
||||
type_inferenced_ast: 571acef2dd154ad80da051c43f402a9d10593c07b234de69fe9fc19284f09849
|
||||
|
@ -16,3 +16,6 @@ outputs:
|
||||
r0:
|
||||
type: bool
|
||||
value: "true"
|
||||
initial_ast: ec1e31c0b1e2cc2cfa1476b9189d1b3e95e786d5b55e4c350a6888860613f4b2
|
||||
canonicalized_ast: dacc5bfe970669abcebe9363e0bc84fe7fb8e0c816dda756b00cc38ae993e781
|
||||
type_inferenced_ast: f8c48aff4a11661fe164e69af32a99a5259f05a10287de26aea2fd323d4744ef
|
||||
|
@ -16,3 +16,6 @@ outputs:
|
||||
r0:
|
||||
type: bool
|
||||
value: "true"
|
||||
initial_ast: 37ec6089b9e1af0c552e259848d1ecd8bb361dd8a5c348d6b34f7f5262dc6f40
|
||||
canonicalized_ast: ad2b199caadb797e02aded3020468c9d7a2b3094652c3b27436b8f98cc71dc05
|
||||
type_inferenced_ast: cb373502d7141af431342592470482ef936a5fc9e6f4ede8a01e8e98537988de
|
||||
|
@ -16,3 +16,6 @@ outputs:
|
||||
r0:
|
||||
type: bool
|
||||
value: "true"
|
||||
initial_ast: b351c4655069ba4e5ae6759b10109406d64b74c652aab8be3547912df3e10c83
|
||||
canonicalized_ast: e9e15873ef2727704b7b4f711516e6f8833a177fe4ff9379823dca293ecb8a72
|
||||
type_inferenced_ast: d040a5aac628379fa32c3e36980f8dac3996a5240bc3482e44c2fdb1d8c3ef60
|
||||
|
@ -34,3 +34,6 @@ outputs:
|
||||
x:
|
||||
type: bool
|
||||
value: "true"
|
||||
initial_ast: 457931d2a45a5872b3f523ee9ed3ae922635750e38048927ee39dcd2fdaf338d
|
||||
canonicalized_ast: 457931d2a45a5872b3f523ee9ed3ae922635750e38048927ee39dcd2fdaf338d
|
||||
type_inferenced_ast: 5268ad28b10aedcd44c0aafced11ed0351999fceb6a202ed5a1faf833da5c2c4
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user