-
Notifications
You must be signed in to change notification settings - Fork 54
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for iterators #169
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great!
Since this is also highly related to the const generic feature , so I think it'd better to be based on the generic PR branch #147.
src/parser/types.rs
Outdated
// for i in 0..5 { ... } | ||
// ^ | ||
let (end, end_span) = match tokens.bump(ctx) { | ||
// here we decide if this for loop is over a range or is an iterator, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not always the case once the generic feature is introduced. For example:
fn range(const START: Field, const END: Field) {
for ii in START..END { // START / END are const generic variables, which are not in numeric form in the syntax.
...
}
}
So I think the safer way to detect whether it is range or iterator can be based on the presence of ..
, which indicates an range.
// for now this means that the expression should have type `Array` | ||
let iterator_typ = self.compute_type(iterator, typed_fn_env)?; | ||
let iterator_typ = | ||
iterator_typ.expect("Could not compute type of iterator (TODO: better error)"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this can be an error thrown with a span, so it can better inform the users where the error is originated in the code.
src/type_checker/checker.rs
Outdated
// exit the scope | ||
typed_fn_env.pop(); | ||
} else { | ||
panic!("Iterator should be an array (TODO: better error)"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same ^
src/circuit_writer/writer.rs
Outdated
@@ -5,6 +5,7 @@ use kimchi::circuits::wires::Wire; | |||
use num_bigint::BigUint; | |||
use num_traits::Num as _; | |||
use serde::{Deserialize, Serialize}; | |||
use toml::value::Array; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
seems unused
Should have addressed most of the things, now merging into One thing to note is that for now the iterator variable is immutable, maybe we could consider adding also mutable iterator variables? For example this code would add one to every element of for mut elem in array {
elem = elem + 1
} though I don't necessarily think that this is a good pattern and I tend to think this should not be allowed, since to me it is not clear if this is mutating the underlying structure or just the local variable |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice. I think that is a good spot. We may come back to this mutable feature if the practical projects really demands it.
There are just a couple of minor issues to fix. The main one is to add the new iterator example to tests. Maybe rename the iterators.no
to generic_iterator.no
as it involves generic and helps differentiate from the existing iterator.no
.
examples/iterators.no
Outdated
@@ -0,0 +1,16 @@ | |||
fn zip(a1: [Field; LEN], a2: [Field; LEN]) -> [[Field; 2]; LEN] { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this new example should be added as a new test in the tests/examples.rs
src/circuit_writer/writer.rs
Outdated
iterator, | ||
body, | ||
} => { | ||
let iterator_expr = self |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe it is better to call it as iterator_var
, since it is of VarOrRef
after the expression has been computed.
src/mast/mod.rs
Outdated
|
||
mono_fn_env.store_type( | ||
&var.value, | ||
&MTypeInfo::new(&array_element_type, var.span, None), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unnecessary & prefix
TyKind::Array(element_type, _len) => *element_type, | ||
TyKind::GenericSizedArray(element_type, _size) => *element_type, | ||
_ => { | ||
return Err(self.error( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe add a negative test (negative_tests.rs
) to cover this scenario, this would help remind this type check should be covered in the tast phase if it happens to refactor at later stage :D
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome work!
This feature is a great fit with the generic arrays. The generic feature enable working with varying length of arrays, while this iterator feature simplifies the use of these generic array and make it practical.
var: Ident, | ||
iterator: Box<Expr>, | ||
body: Vec<Stmt>, | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
late to the party, but wouldn't it be cleaner (and perhaps safer since forloops have annoying logic for generics) to have a common structure for them?
ForLoop {
var: Ident,
range: RangeOrIterator,
body: Vec<Stmt>,
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cf #177
This PR aims at addressing issue #132 by introducing the possibility to iterate over arrays.
This makes it possible to write a circuit like this
This also improves the
iterate.no
test as mentioned in the issue