-
Notifications
You must be signed in to change notification settings - Fork 38
Stdlib: Binary/Byte stream utilities #923
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
base: master
Are you sure you want to change the base?
Conversation
Another use case is https://github.com/effekt-community/effekt-rejit/ . |
cf907f6
to
96c0eed
Compare
Broken on LLVM, by Valgrind and missing generic stuff (for tests) |
0792602
to
a2f38de
Compare
Tiny & fast exponentiation using streams: <img width="491" alt="Screenshot 2025-04-05 at 16 04 07" src="https://github.com/user-attachments/assets/0ec1cdf1-6c86-4fa4-890f-063540c083f4" /> The approach is simple: to calculate `n^k`, zip squares of `n` (`n`, `n^2`, `n^4`, ...) with the bits of `k`. Sketch: ``` n^k = n^0b10011 = (1 * n^0b10000) * (0 * n^0b01000) * (0 * n^0b00100) * (1 * n^0b00010) * (1 * n^0b00001) ``` Also drags a few other changes along: - `product` and `iterate` in `stream` - temporary addition of `eachLSB` and `eachMSB` -- these would probably be better off using the toolchain from #923, but I don't want to forget about the example I'm adding it because: 1. it's a fun, small example, 2. it uses a bunch of different combinators, 3. it uses the new multiple param lambda case syntax (#914), 4. and it has some missed opt opportunities, I think.
The generated identifiers in the IR seem non-deterministic between execution environments: one can observe different names locally vs on the CI. This led to test failures in entirely unrelated PRs (#930, #923). As this is blocking the other PRs, I propose the hotfix contained in this PR. I'm also open to better suggestions on how to write this particular test case or on how to fix the non-determinism.
dfeb01b
to
1f24f64
Compare
Co-authored-by: Jiří Beneš <[email protected]>
1f24f64
to
d5c61a8
Compare
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.
LGTM, mostly just nitpicks / questions 👀
@@ -0,0 +1,349 @@ | |||
import option |
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.
Naming 🚲 🏠
- Should this be a top-level module like
binstream
or a nested one likestream/binary
/stream/bin
...? - Is it a binary stream or a bit stream?
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.
- I do not care. It could be nested.
- It is byte and bit streams. So, very much open to suggestions.
} | ||
with splice[OfWidth[BE[Signed[Int]]]] { i => | ||
collectList[Bit]{ | ||
if(i.raw.raw.raw < 0){ |
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.
My kingdom for newtype
s? :)
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.
Yes. It is somewhat nice use-wise, but this really should be something like a newtype - or us adding formatting specifiers to splices in some other form.
examples/stdlib/binstream.effekt
Outdated
test("int back-and-forth (17), explicit BE"){ assert(x"${17.BE}", 17) } | ||
test("int back-and-forth (17), explicit LE"){ assert(x"${17.LE}", 17 * 256 * 256 * 256) } | ||
test("byte 00101010"){ | ||
with on[MissingValue].default{ assert(true, false) } |
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.
Since we're changing test
anyway, could we add a on[MissingValue].assertSome
?
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.
Yes, good idea. TODO.
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.
effekt/libraries/common/test.effekt
Lines 62 to 73 in 3d973b2
def assertNotThrown[E](ex: on[E]){ body: => Unit / Exception[E] }: Unit / Assertion = { | |
ex.default{ do assert(false, "Unexpected Exception") }{body} | |
} | |
def assertNoThrow[E]{ body: => Unit / Exception[E] }: Unit / Assertion = { | |
on[E].default{ do assert(false, "Unexpected Exception") }{body} | |
} | |
def assertThrown[E](ex: on[E]){ body: => Unit / Exception[E] }: Unit / Assertion = { | |
do assert(ex.default{ true }{ body(); false }, "Expected Exception, but exited normally") | |
} | |
def assertThrows[E]{body: => Unit / Exception[E] }: Unit / Assertion = { | |
do assert(on[E].default{ true }{ body(); false }, "Expected Exception, but exited normally") | |
} |
WDYT?
This adds a
binstream
file to the stdlib that can be used to easily create streams of bytes.See #870 for a usage example (this was mostly factored out from there).