Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Support Generators, function*, and yield #5079

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

Open
armanbilge opened this issue Nov 20, 2024 · 6 comments · May be fixed by #5082
Open

Support Generators, function*, and yield #5079

armanbilge opened this issue Nov 20, 2024 · 6 comments · May be fixed by #5082
Labels
language Affects language semantics.

Comments

@armanbilge
Copy link
Member

I think this would enable suspension and thus implementation of coroutines directly in Scala.js (i.e. without needing a monadic datatype and a runtime interpreter of said datatype).

@sjrd
Copy link
Member

sjrd commented Nov 20, 2024

No it wouldn't. yields must be lexically in a generator function. They cannot suspend across stack frames.

That means it's nothing that a Scala macro couldn't do with local transformations. There is no need to have dedicated language support for that.

If generators had brought a unique superpower like coroutining, we would have added support for them years ago, already in the 0.6.x era.


Related: #5064
That does actually bring such a superpower. But it's only going to work on Wasm.

@gzm0
Copy link
Contributor

gzm0 commented Nov 20, 2024

@sjrd do you have any feel for whether generator chaining is optimized by VMs? (e.g. await-ing a promise created by a generator func might be much more efficient than an arbitrary promise).

@sjrd
Copy link
Member

sjrd commented Nov 20, 2024

Generators and await are two different things. Generators are not Promises. Well they're orthogonal: you can write an async generator, but that composes the notion of a generator with that an async function.

Anyway, good question. For async/await, I would be surprised if they are optimized in any specific way, because by spec each await must happen in a separate microtask of the job queue. For generators and yield, it's possible that they do something clever. I haven't seen anything about it, but I haven't been looking either.

@armanbilge
Copy link
Member Author

Thanks for the reply :)


yields must be lexically in a generator function. They cannot suspend across stack frames.

Yes, that is correct. So while it is not possible to implement stackful coroutines, it is possible to implement stackless coroutines using yield.


That means it's nothing that a Scala macro couldn't do with local transformations. There is no need to have dedicated language support for that.

I didn't realize that this is something that could be implemented with a macro instead of a compiler plugin.

In any case, I also wondered if there would be a performance advantage to preferring yield.

@armanbilge
Copy link
Member Author

armanbilge commented Nov 20, 2024

Here is a recent document about the implementation of generators in V8.

https://docs.google.com/document/d/1-iFoVuvpIEjA9dtSsOjmKL5vAzzvf0cKI6f4zaObiV8/

Edit with my thoughts:

  • Maglev and Turboshaft refer to V8's optimizing compilers. The fact that support for yield exists at multiple compiler levels (and not simply an early AST-level rewrite) suggests to me that they are applying optimizations that would not be possible to achieve with local transformations of Scala code.

  • Additionally, it seems like await may also be implemented in terms of generators. So there may be a performance advantage here as well over the equivalent Scala plugins.

sjrd added a commit to sjrd/scala-js that referenced this issue Nov 26, 2024
Would fix scala-js#5079.

* `async/await` works on JS and Wasm. The latter uses the JSPI proposal.
* `function*/yield` only works on JS.
* `yield_*` should work (on JS) but is untested.
* `async function*` has theoretical support in the linker, but no
  support in the compiler backend for now.
@sjrd sjrd linked a pull request Nov 26, 2024 that will close this issue
@sjrd
Copy link
Member

sjrd commented Nov 26, 2024

Proof of concept: #5082.

Feel free to try it out. If you can get some benchmarks with measurable improvements, that would give a good case to push this further.

sjrd added a commit to sjrd/scala-js that referenced this issue Nov 26, 2024
Would fix scala-js#5079.

* `async/await` works on JS and Wasm. The latter uses the JSPI proposal.
* `function*/yield` only works on JS.
* `yield_*` should work (on JS) but is untested.
* `async function*` has theoretical support in the linker, but no
  support in the compiler backend for now.
sjrd added a commit to sjrd/scala-js that referenced this issue Dec 1, 2024
Would fix scala-js#5079.

* `async/await` works on JS and Wasm. The latter uses the JSPI proposal.
* `function*/yield` only works on JS.
* `yield_*` should work (on JS) but is untested.
* `async function*` has theoretical support in the linker, but no
  support in the compiler backend for now.
@sjrd sjrd added the language Affects language semantics. label Dec 9, 2024
sjrd added a commit to sjrd/scala-js that referenced this issue Feb 6, 2025
Would fix scala-js#5079.

* `async/await` works on JS and Wasm. The latter uses the JSPI proposal.
* `function*/yield` only works on JS.
* `yield_*` should work (on JS) but is untested.
* `async function*` has theoretical support in the linker, but no
  support in the compiler backend for now.
sjrd added a commit to sjrd/scala-js that referenced this issue Feb 7, 2025
Would fix scala-js#5079.

* `async/await` works on JS and Wasm. The latter uses the JSPI proposal.
* `function*/yield` only works on JS.
* `yield_*` should work (on JS) but is untested.
* `async function*` has theoretical support in the linker, but no
  support in the compiler backend for now.
sjrd added a commit to sjrd/scala-js that referenced this issue Apr 6, 2025
Would fix scala-js#5079.

* Only only works on JS; not on Wasm.
* `yield_*` should work (on JS) but is untested.
* `async function*` has theoretical support in the linker, but no
  support in the compiler backend for now.
sjrd added a commit to sjrd/scala-js that referenced this issue Apr 7, 2025
Would fix scala-js#5079.

* Only only works on JS; not on Wasm.
* `yield_*` should work (on JS) but is untested.
* `async function*` has theoretical support in the linker, but no
  support in the compiler backend for now.
sjrd added a commit to sjrd/scala-js that referenced this issue Apr 8, 2025
Would fix scala-js#5079.

* Only only works on JS; not on Wasm.
* `yield_*` should work (on JS) but is untested.
* `async function*` has theoretical support in the linker, but no
  support in the compiler backend for now.
sjrd added a commit to sjrd/scala-js that referenced this issue Apr 14, 2025
Would fix scala-js#5079.

* Only only works on JS; not on Wasm.
* `yield_*` should work (on JS) but is untested.
* `async function*` has theoretical support in the linker, but no
  support in the compiler backend for now.
sjrd added a commit to sjrd/scala-js that referenced this issue Apr 22, 2025
Would fix scala-js#5079.

* Only works on JS; not on Wasm.
* `yield_*` should work (on JS) but is untested.
* `async function*` has theoretical support in the linker, but no
  support in the compiler backend for now.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
language Affects language semantics.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants