mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-12-23 18:21:38 +03:00
Merge branch 'master' of github.com:AleoHQ/leo into bug/abnf-format-strings
This commit is contained in:
commit
c1879e6e1c
@ -148,24 +148,28 @@ impl<'a> FromAst<'a, leo_ast::ArrayRangeAccessExpression> for ArrayRangeAccessEx
|
|||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
let const_right = match right.map(|x| x.const_value()) {
|
let const_right = match right.map(|x| x.const_value()) {
|
||||||
Some(Some(ConstValue::Int(value))) => {
|
Some(Some(ConstValue::Int(inner_value))) => {
|
||||||
let value = value.to_usize();
|
let usize_value = inner_value.to_usize();
|
||||||
if let Some(value) = value {
|
if let Some(inner_value) = usize_value {
|
||||||
if value > parent_size {
|
if inner_value > parent_size {
|
||||||
return Err(AsgConvertError::array_index_out_of_bounds(
|
let error_span = if let Some(right) = right {
|
||||||
value,
|
right.span().cloned().unwrap_or_default()
|
||||||
&right.unwrap().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 {
|
} else if let Some(left) = const_left {
|
||||||
if left > value {
|
if left > inner_value {
|
||||||
return Err(AsgConvertError::array_index_out_of_bounds(
|
let error_span = if let Some(right) = right {
|
||||||
value,
|
right.span().cloned().unwrap_or_default()
|
||||||
&right.unwrap().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 => Some(parent_size),
|
||||||
_ => None,
|
_ => None,
|
||||||
@ -188,12 +192,14 @@ impl<'a> FromAst<'a, leo_ast::ArrayRangeAccessExpression> for ArrayRangeAccessEx
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(value) = const_left {
|
if let Some(left_value) = const_left {
|
||||||
if value + expected_len > parent_size {
|
if left_value + expected_len > parent_size {
|
||||||
return Err(AsgConvertError::array_index_out_of_bounds(
|
let error_span = if let Some(left) = left {
|
||||||
value,
|
left.span().cloned().unwrap_or_default()
|
||||||
&left.unwrap().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);
|
length = Some(expected_len);
|
||||||
|
@ -25,9 +25,7 @@ that we suggest few changes to Leo CLI and Manifest:
|
|||||||
- allow custom names for imports to manually resolve name conflicts;
|
- allow custom names for imports to manually resolve name conflicts;
|
||||||
- add "curve" and "proving system" sections to the Manifest;
|
- add "curve" and "proving system" sections to the Manifest;
|
||||||
- add "include" and "exclude" parameters for "proving system" and "curve";
|
- add "include" and "exclude" parameters for "proving system" and "curve";
|
||||||
|
- add a lock file which would store imported dependencies and their relations;
|
||||||
Later this solution can be improved by adding a lock-file which would lock
|
|
||||||
imported packages based on both their contents and version.
|
|
||||||
|
|
||||||
# Motivation
|
# Motivation
|
||||||
|
|
||||||
@ -109,12 +107,7 @@ To support updated Manifest new command should be added to Leo CLI.
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# pull imports
|
# pull imports
|
||||||
leo install
|
leo fetch
|
||||||
```
|
|
||||||
|
|
||||||
Alternatively it can be called `pull`.
|
|
||||||
```
|
|
||||||
leo pull
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Imports Restructurization
|
## Imports Restructurization
|
||||||
@ -155,6 +148,44 @@ first-program => author1-program@0.1.0
|
|||||||
second-program => author2-program2@1.0.4
|
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
|
## Recursive Dependencies
|
||||||
|
|
||||||
This improvement introduces recursive dependencies. To solve this case preemptively
|
This improvement introduces recursive dependencies. To solve this case preemptively
|
||||||
|
@ -94,6 +94,26 @@ for i in 0..5 {}
|
|||||||
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
|
## Example
|
||||||
|
|
||||||
The code example demostrated in the Motivation part of this document
|
The code example demostrated in the Motivation part of this document
|
||||||
|
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];
|
||||||
|
}
|
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;
|
@ -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'"
|
Loading…
Reference in New Issue
Block a user