mirror of
https://github.com/AleoHQ/leo.git
synced 2024-12-19 15:41:36 +03:00
Merge pull request #1184 from AleoHQ/feature/countdown-loops
[Implementation] Countdown Loops
This commit is contained in:
commit
f14182097f
@ -341,6 +341,7 @@ pub trait ReconstructingReducerStatement<'a>: ReconstructingReducerExpression<'a
|
|||||||
variable: input.variable,
|
variable: input.variable,
|
||||||
start: Cell::new(start),
|
start: Cell::new(start),
|
||||||
stop: Cell::new(stop),
|
stop: Cell::new(stop),
|
||||||
|
inclusive: input.inclusive,
|
||||||
body: Cell::new(body),
|
body: Cell::new(body),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,7 @@ pub struct IterationStatement<'a> {
|
|||||||
pub variable: &'a Variable<'a>,
|
pub variable: &'a Variable<'a>,
|
||||||
pub start: Cell<&'a Expression<'a>>,
|
pub start: Cell<&'a Expression<'a>>,
|
||||||
pub stop: Cell<&'a Expression<'a>>,
|
pub stop: Cell<&'a Expression<'a>>,
|
||||||
|
pub inclusive: bool,
|
||||||
pub body: Cell<&'a Statement<'a>>,
|
pub body: Cell<&'a Statement<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,6 +94,7 @@ impl<'a> FromAst<'a, leo_ast::IterationStatement> for &'a Statement<'a> {
|
|||||||
variable,
|
variable,
|
||||||
stop: Cell::new(stop),
|
stop: Cell::new(stop),
|
||||||
start: Cell::new(start),
|
start: Cell::new(start),
|
||||||
|
inclusive: statement.inclusive,
|
||||||
body: Cell::new(
|
body: Cell::new(
|
||||||
scope
|
scope
|
||||||
.context
|
.context
|
||||||
@ -114,6 +116,7 @@ impl<'a> Into<leo_ast::IterationStatement> for &IterationStatement<'a> {
|
|||||||
variable: self.variable.borrow().name.clone(),
|
variable: self.variable.borrow().name.clone(),
|
||||||
start: self.start.get().into(),
|
start: self.start.get().into(),
|
||||||
stop: self.stop.get().into(),
|
stop: self.stop.get().into(),
|
||||||
|
inclusive: self.inclusive,
|
||||||
block: match self.body.get() {
|
block: match self.body.get() {
|
||||||
Statement::Block(block) => block.into(),
|
Statement::Block(block) => block.into(),
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
|
@ -382,6 +382,7 @@ impl Canonicalizer {
|
|||||||
variable: iteration.variable.clone(),
|
variable: iteration.variable.clone(),
|
||||||
start,
|
start,
|
||||||
stop,
|
stop,
|
||||||
|
inclusive: iteration.inclusive,
|
||||||
block,
|
block,
|
||||||
span: iteration.span.clone(),
|
span: iteration.span.clone(),
|
||||||
})
|
})
|
||||||
|
@ -359,6 +359,7 @@ pub trait ReconstructingReducer {
|
|||||||
variable,
|
variable,
|
||||||
start,
|
start,
|
||||||
stop,
|
stop,
|
||||||
|
inclusive: iteration.inclusive,
|
||||||
block,
|
block,
|
||||||
span: iteration.span.clone(),
|
span: iteration.span.clone(),
|
||||||
})
|
})
|
||||||
|
@ -24,16 +24,18 @@ pub struct IterationStatement {
|
|||||||
pub variable: Identifier,
|
pub variable: Identifier,
|
||||||
pub start: Expression,
|
pub start: Expression,
|
||||||
pub stop: Expression,
|
pub stop: Expression,
|
||||||
|
pub inclusive: bool,
|
||||||
pub block: Block,
|
pub block: Block,
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for IterationStatement {
|
impl fmt::Display for IterationStatement {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
let eq = if self.inclusive { "=" } else { "" };
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
"for {} in {}..{} {}",
|
"for {} in {}..{}{} {}",
|
||||||
self.variable, self.start, self.stop, self.block
|
self.variable, self.start, eq, self.stop, self.block
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,14 @@ impl<'a, F: PrimeField, G: GroupType<F>> ConstrainedProgram<'a, F, G> {
|
|||||||
.to_usize()
|
.to_usize()
|
||||||
.ok_or_else(|| StatementError::loop_index_const(&span))?;
|
.ok_or_else(|| StatementError::loop_index_const(&span))?;
|
||||||
|
|
||||||
for i in from..to {
|
let iter: Box<dyn Iterator<Item = usize>> = match (from < to, statement.inclusive) {
|
||||||
|
(true, true) => Box::new(from..=to),
|
||||||
|
(true, false) => Box::new(from..to),
|
||||||
|
(false, true) => Box::new((to..=from).rev()),
|
||||||
|
(false, false) => Box::new((to..from).rev()),
|
||||||
|
};
|
||||||
|
|
||||||
|
for i in iter {
|
||||||
// Store index in current function scope.
|
// Store index in current function scope.
|
||||||
// For loop scope is not implemented.
|
// For loop scope is not implemented.
|
||||||
let variable = statement.variable.borrow();
|
let variable = statement.variable.borrow();
|
||||||
|
@ -231,6 +231,8 @@ impl Namespace for CompileNamespace {
|
|||||||
.unwrap_or_else(|_| "Error converting ast to string.".to_string()),
|
.unwrap_or_else(|_| "Error converting ast to string.".to_string()),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
std::fs::remove_dir_all(std::path::Path::new("/tmp/output")).expect("Error failed to clean up output dir.");
|
||||||
|
|
||||||
let final_output = CompileOutput {
|
let final_output = CompileOutput {
|
||||||
circuit: last_circuit.unwrap(),
|
circuit: last_circuit.unwrap(),
|
||||||
output: output_items,
|
output: output_items,
|
||||||
|
Binary file not shown.
@ -936,7 +936,7 @@ conditional-statement = branch
|
|||||||
; that goes from a starting value (inclusive) to an ending value (exclusive).
|
; that goes from a starting value (inclusive) to an ending value (exclusive).
|
||||||
; The body is a block.
|
; The body is a block.
|
||||||
|
|
||||||
loop-statement = %s"for" identifier %s"in" expression ".." expression block
|
loop-statement = %s"for" identifier %s"in" expression ".." [ "=" ] expression block
|
||||||
|
|
||||||
; An assignment statement is straightforward.
|
; An assignment statement is straightforward.
|
||||||
; Based on the operator, the assignment may be simple (i.e. `=`)
|
; Based on the operator, the assignment may be simple (i.e. `=`)
|
||||||
|
@ -217,6 +217,7 @@ impl ParserContext {
|
|||||||
self.expect(Token::In)?;
|
self.expect(Token::In)?;
|
||||||
let start = self.parse_expression()?;
|
let start = self.parse_expression()?;
|
||||||
self.expect(Token::DotDot)?;
|
self.expect(Token::DotDot)?;
|
||||||
|
let inclusive = self.eat(Token::Assign).is_some();
|
||||||
self.fuzzy_struct_state = true;
|
self.fuzzy_struct_state = true;
|
||||||
let stop = self.parse_conditional_expression()?;
|
let stop = self.parse_conditional_expression()?;
|
||||||
self.fuzzy_struct_state = false;
|
self.fuzzy_struct_state = false;
|
||||||
@ -227,6 +228,7 @@ impl ParserContext {
|
|||||||
variable: ident,
|
variable: ident,
|
||||||
start,
|
start,
|
||||||
stop,
|
stop,
|
||||||
|
inclusive,
|
||||||
block,
|
block,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
29
tests/compiler/statements/all_loops.leo
Normal file
29
tests/compiler/statements/all_loops.leo
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
namespace: Compile
|
||||||
|
expectation: Pass
|
||||||
|
input_file: inputs/dummy.in
|
||||||
|
*/
|
||||||
|
|
||||||
|
function main(k: bool) -> bool {
|
||||||
|
let reverse: u32 = 0;
|
||||||
|
for i in 10..0 {
|
||||||
|
reverse += i;
|
||||||
|
}
|
||||||
|
|
||||||
|
let forward: u32 = 0;
|
||||||
|
for x in 0..10 {
|
||||||
|
forward += x;
|
||||||
|
}
|
||||||
|
|
||||||
|
let reverse_inclusive: u32 = 0;
|
||||||
|
for a in 10..=0 {
|
||||||
|
reverse_inclusive += a;
|
||||||
|
}
|
||||||
|
|
||||||
|
let forward_inclusive: u32 = 0;
|
||||||
|
for b in 0..=10 {
|
||||||
|
forward_inclusive += b;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (reverse == forward) && (reverse_inclusive == forward_inclusive) && k;
|
||||||
|
}
|
@ -16,6 +16,6 @@ outputs:
|
|||||||
r0:
|
r0:
|
||||||
type: bool
|
type: bool
|
||||||
value: "true"
|
value: "true"
|
||||||
initial_ast: e04195ede456babe4121950806163d2cc8c1e4b0180a37969099749ae3dfc3b9
|
initial_ast: c983e5e79b4325ac133ac1a5ff0b1655c646111389991286322b8c16c5833837
|
||||||
canonicalized_ast: a8673bb8b05eb0289435b8b2335402f022df9ff46db523707cc61eca1b9679ad
|
canonicalized_ast: 8dcb714238ef7e9fd3c66a7a12ec4621bb4e9ac5994f1c692215a9f93463ce9e
|
||||||
type_inferenced_ast: afeabed72941728dc8a8cc0ed27d1e8170f7dd477275be29e794b6c28142f2a7
|
type_inferenced_ast: ebd34799bd1c6936ca5032812d2466bade58df616cc06e3c6e57151a06b78601
|
||||||
|
@ -16,6 +16,6 @@ outputs:
|
|||||||
r0:
|
r0:
|
||||||
type: bool
|
type: bool
|
||||||
value: "true"
|
value: "true"
|
||||||
initial_ast: 7dcfb3d46fc2a3f91d57f21db97e0d3829d0ac438a09fe0beaaa83aa0c545947
|
initial_ast: 96155896f4993bd97a8e15281e92c4e9352ed02343bccddb9c3cd0f8ca55b408
|
||||||
canonicalized_ast: 33ffbf095e9050dd55b3e5cae0518f47b61689a7cefb5dd2d454ff6c4bb2fc9c
|
canonicalized_ast: ae4a2dfa82f00621192f117bea664e58768d57376b68a90ce0e15c5bc9535e22
|
||||||
type_inferenced_ast: a6cff2181d7642f4a729d2301708c97956fc60322c8680a7d2d71296f4e7a5c6
|
type_inferenced_ast: 2452ad985e23efbc07a94f2945d406a959aca68ec37e9c349a30edcc12839c04
|
||||||
|
@ -16,6 +16,6 @@ outputs:
|
|||||||
r0:
|
r0:
|
||||||
type: bool
|
type: bool
|
||||||
value: "true"
|
value: "true"
|
||||||
initial_ast: cb4033ff1a05ae4b09fd9bbbeddd11b0fddececb98f96c7aef2ebb3069748870
|
initial_ast: 55bf6a745bd0da1684239dd5f624a5ead1d5644c15f25e3099ff40c71ce23317
|
||||||
canonicalized_ast: 6607510f1df2682091711014cb0b1db8b786707accbab9c1760d710bed32ca17
|
canonicalized_ast: 929e1e876d7dd5d04ae39dd8d4b0b3fa3f0e8783e39056941115fff337a0ef84
|
||||||
type_inferenced_ast: 4b5f83f6029a04c1fbce48e596ac2d7d0d97b87489b05656ff8773b04d2597fd
|
type_inferenced_ast: bc6903d0764db54fd4938835120ab6fa02575b1b896828876153bb30da28a19a
|
||||||
|
@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
namespace: Compile
|
||||||
|
expectation: Pass
|
||||||
|
outputs:
|
||||||
|
- circuit:
|
||||||
|
num_public_variables: 0
|
||||||
|
num_private_variables: 1
|
||||||
|
num_constraints: 1
|
||||||
|
at: 042610d0fd1fe6d6ac112138f8755752f44c7d2a00f1b5960574d6da5cda393f
|
||||||
|
bt: e97756698880ab7555a959a5fb5c6b4e15bd64612aa677adbfe2d0bd91f0a83c
|
||||||
|
ct: cf1cbb66a638b4860a516671fb74850e6ccf787fe6c4c8d29e9c04efe880bd05
|
||||||
|
output:
|
||||||
|
- input_file: inputs/dummy.in
|
||||||
|
output:
|
||||||
|
registers:
|
||||||
|
r0:
|
||||||
|
type: bool
|
||||||
|
value: "true"
|
||||||
|
initial_ast: 7ecd56e44c6b1cb4f702a2712a2a7fe3bf564dac26a70e1f14151a688fb24769
|
||||||
|
canonicalized_ast: 360ecac21f95b0e1d949d49458f2c4557446d01db08333d6f25621ef47a78a66
|
||||||
|
type_inferenced_ast: 853fdefe080011aaa35363e827a527ab7ce6c7e93cd568c8a150211fa6e402fe
|
@ -16,6 +16,6 @@ outputs:
|
|||||||
a:
|
a:
|
||||||
type: bool
|
type: bool
|
||||||
value: "true"
|
value: "true"
|
||||||
initial_ast: 8374ac96fbf6d918998ebe6ccb88842f2141efbc721314ff1b98a6e57c30ac8c
|
initial_ast: cce56dc8d678cd645e8fb3043aeb95bd24f94640e08219f00b7b9db66498ec29
|
||||||
canonicalized_ast: 031149b98d685b26166d621c2206142438479414eeae8db5f92927aabca5d684
|
canonicalized_ast: 914f4ba5fc0c5148f1e105af4f857b8b12d29a609d47a366c73fd3d2f8eda3bf
|
||||||
type_inferenced_ast: 94959ec2fc0be13f8943a54261f6c23c6585773bc14936ee68a3f7289cc8bd26
|
type_inferenced_ast: 02b16a3b3a7e7c7ca4803292ea1f5410f293f2000f21c0a5245f2e5273561f06
|
||||||
|
@ -16,6 +16,6 @@ outputs:
|
|||||||
a:
|
a:
|
||||||
type: bool
|
type: bool
|
||||||
value: "true"
|
value: "true"
|
||||||
initial_ast: 2af258377cc5af8e1bed75bed8dd57d2ecb969f71b8081a321a946df782ead97
|
initial_ast: 1c9abdc059f6649b381be12d435129702a048f941b5766212105d9f20c6479cf
|
||||||
canonicalized_ast: 8733ab382dd7d3d506f999dd6b34442200e447cb530cc6d8115da6267b176f2e
|
canonicalized_ast: 5a8d9b146b28300345c3f0878f712ccc7a545534dc820d22180ec7bff8b96713
|
||||||
type_inferenced_ast: 6f4c12b70f5fb244fbca65cb32e68c88ced6bf289afb7b1639257bb8de9a4bbb
|
type_inferenced_ast: 259654bcec24b6110db951fef9ee504455219c9e1860cc96b30d18ecf8fc2ead
|
||||||
|
@ -16,6 +16,6 @@ outputs:
|
|||||||
a:
|
a:
|
||||||
type: bool
|
type: bool
|
||||||
value: "true"
|
value: "true"
|
||||||
initial_ast: 5223011087228b526071851038df390424ca442c4b21e0001cdf14bf8c63cf2c
|
initial_ast: 3ac3ba48fb628fff67489c5d1502c3e0aaf9e197bf54d8c544fc79d9c83e3e16
|
||||||
canonicalized_ast: ab0a3a3caa5250c522c9eaa4b4bee5e36c179f856b02c2cdf94b4798344daf3d
|
canonicalized_ast: c081654e7bd5edbfc1653444e73bc2f5e5b4e887f3e99dbb54f26cbfa37d84e1
|
||||||
type_inferenced_ast: 5825d1694362e1dab8710cbfa4feb608f968a98052a01fa36c152e06c1bd2cc4
|
type_inferenced_ast: 23cddd23376a87be6e293bb4eae4470c9e450984bace87dc7386a5bf37081af0
|
||||||
|
@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
namespace: Compile
|
||||||
|
expectation: Pass
|
||||||
|
outputs:
|
||||||
|
- circuit:
|
||||||
|
num_public_variables: 0
|
||||||
|
num_private_variables: 1
|
||||||
|
num_constraints: 1
|
||||||
|
at: 042610d0fd1fe6d6ac112138f8755752f44c7d2a00f1b5960574d6da5cda393f
|
||||||
|
bt: e97756698880ab7555a959a5fb5c6b4e15bd64612aa677adbfe2d0bd91f0a83c
|
||||||
|
ct: cf1cbb66a638b4860a516671fb74850e6ccf787fe6c4c8d29e9c04efe880bd05
|
||||||
|
output:
|
||||||
|
- input_file: inputs/dummy.in
|
||||||
|
output:
|
||||||
|
registers:
|
||||||
|
r0:
|
||||||
|
type: bool
|
||||||
|
value: "true"
|
||||||
|
initial_ast: 75fbb3ed1613fbf39ce803ff903befe209b26a953ba8db1d68e35066655d96e6
|
||||||
|
canonicalized_ast: a96cae2c9e347245e07c63b5c94cf43497063c3f548c615627da4b1775e9a17b
|
||||||
|
type_inferenced_ast: dc663974ed1cce7b15c35eda29c9b1af5426eafddbd108b5a03cd7071ad4a6bc
|
@ -24,6 +24,7 @@ outputs:
|
|||||||
col_stop: 14
|
col_stop: 14
|
||||||
path: test
|
path: test
|
||||||
content: "for x in 0..7 {}"
|
content: "for x in 0..7 {}"
|
||||||
|
inclusive: false
|
||||||
block:
|
block:
|
||||||
statements: []
|
statements: []
|
||||||
span:
|
span:
|
||||||
@ -62,6 +63,7 @@ outputs:
|
|||||||
col_stop: 14
|
col_stop: 14
|
||||||
path: test
|
path: test
|
||||||
content: "for x in 0..7 {"
|
content: "for x in 0..7 {"
|
||||||
|
inclusive: false
|
||||||
block:
|
block:
|
||||||
statements:
|
statements:
|
||||||
- Return:
|
- Return:
|
||||||
@ -119,6 +121,7 @@ outputs:
|
|||||||
col_stop: 17
|
col_stop: 17
|
||||||
path: test
|
path: test
|
||||||
content: "for x in 0..99u8 {"
|
content: "for x in 0..99u8 {"
|
||||||
|
inclusive: false
|
||||||
block:
|
block:
|
||||||
statements:
|
statements:
|
||||||
- Return:
|
- Return:
|
||||||
@ -167,6 +170,7 @@ outputs:
|
|||||||
content: "for x in 0..Self {"
|
content: "for x in 0..Self {"
|
||||||
stop:
|
stop:
|
||||||
Identifier: "{\"name\":\"Self\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":13,\\\"col_stop\\\":17,\\\"path\\\":\\\"test\\\",\\\"content\\\":\\\"for x in 0..Self {\\\"}\"}"
|
Identifier: "{\"name\":\"Self\",\"span\":\"{\\\"line_start\\\":1,\\\"line_stop\\\":1,\\\"col_start\\\":13,\\\"col_stop\\\":17,\\\"path\\\":\\\"test\\\",\\\"content\\\":\\\"for x in 0..Self {\\\"}\"}"
|
||||||
|
inclusive: false
|
||||||
block:
|
block:
|
||||||
statements:
|
statements:
|
||||||
- Return:
|
- Return:
|
||||||
|
Loading…
Reference in New Issue
Block a user