Skip to content

Conversation

marzipankaiser
Copy link
Contributor

@marzipankaiser marzipankaiser commented Apr 1, 2025

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

@marzipankaiser
Copy link
Contributor Author

Another use case is https://github.com/effekt-community/effekt-rejit/ .

@marzipankaiser
Copy link
Contributor Author

Broken on LLVM, by Valgrind and missing generic stuff (for tests)

jiribenes added a commit that referenced this pull request May 6, 2025
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.
timsueberkrueb added a commit that referenced this pull request May 7, 2025
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.
@marzipankaiser marzipankaiser marked this pull request as ready for review May 7, 2025 11:04
@b-studios b-studios self-requested a review May 12, 2025 14:56
Copy link
Contributor

@jiribenes jiribenes left a 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 👀

:shipit:

@@ -0,0 +1,349 @@
import option
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Naming 🚲 🏠

  1. Should this be a top-level module like binstream or a nested one like stream/binary / stream/bin...?
  2. Is it a binary stream or a bit stream?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. I do not care. It could be nested.
  2. 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){
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My kingdom for newtypes? :)

Copy link
Contributor Author

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.

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) }
Copy link
Contributor

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?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, good idea. TODO.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants