Merge pull request #1184 from AleoHQ/feature/countdown-loops

[Implementation] Countdown Loops
This commit is contained in:
Alessandro Coglio 2021-07-23 18:03:09 -07:00 committed by GitHub
commit f14182097f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 116 additions and 22 deletions

View File

@ -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),
}) })
} }

View File

@ -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!(),

View File

@ -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(),
}) })

View File

@ -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(),
}) })

View File

@ -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
) )
} }
} }

View File

@ -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();

View File

@ -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.

View File

@ -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. `=`)

View File

@ -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,
}) })
} }

View 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;
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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: