Skip to content
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

Editorial: enable built-in async and sync generator functions to be specified #1665

Open
wants to merge 4 commits into
base: master
from

Conversation

@devsnek
Copy link
Member

commented Aug 11, 2019

This is a precursor to https://github.com/tc39/proposal-iterator-helpers, and probably can be integrated into that proposal at some point, but I wanted to get some feedback on this approach before then. I think this change is definitely worth exploring for the purpose of the clarity and maintainability of the specification. You can compare the current iterator methods (https://tc39.es/proposal-iterator-helpers) with what the spec text looks like with this change:

<h1>%IteratorPrototype%.map ( _mapper_ )</h1>
<p>%IteratorPrototype%.map is a built-in generator function which, when called, performs the following prelude steps:</p>
<emu-alg>
  1. Let _iterated_ be ? GetIteratorDirect(*this* value).
  1. If IsCallable(_mapper_) is *false*, throw a *TypeError* exception.
</emu-alg>
<p>The body of %IteratorPrototype%.map is composed of the following steps:</p>
<emu-alg>
  1. Repeat,
    1. Let _next_ be ? IteratorStep(_iterated_).
    1. If _next_ is *false*, return *undefined*.
    1. Let _value_ be ? IteratorValue(_next_).
    1. Let _mapped_ be ? Call(_mapper_, *undefined*, &laquo; _value_ &raquo;).
    1. Perform ? Yield(_mapped_).
</emu-alg>
@ljharb
Copy link
Member

left a comment

Would it be perhaps helpful in demonstrating the change to refactor the matchAll iterator algorithm steps to be a built-in generator function?

Show resolved Hide resolved spec.html
Show resolved Hide resolved spec.html
@devsnek

This comment has been minimized.

Copy link
Member Author

commented Aug 12, 2019

@ljharb here's what i think RegExp.prototype[@@matchAll] would look like. Obviously though we can't do this now because RegExpStringIteratorPrototype is observable.

<p>RegExp.prototype[@@matchAll] is a built-in generator function which, when called, performs the following prelude steps:</p>
<emu-alg>
  1. Let _R_ be the *this* value.
  1. If Type(_R_) is not Object, throw a *TypeError* exception.
  1. Let _S_ be ? ToString(_string_).
  1. Let _C_ be ? SpeciesConstructor(_R_, %RegExp%).
  1. Let _flags_ be ? ToString(? Get(_R_, `"flags"`)).
  1. Let _matcher_ be ? Construct(_C_, &laquo; _R_, _flags_ &raquo;).
  1. Let _lastIndex_ be ? ToLength(? Get(_R_, `"lastIndex"`)).
  1. Perform ? Set(_matcher_, `"lastIndex"`, _lastIndex_, *true*).
<emu-alg>
<p>The body of RegExp.prototype[@@matchAll] is composed of the following steps:</p>
<emu-alg>
  1. If _flags_ contains `"g"`, let _global_ be *true*.
  1. Else, let _global_ be *false*.
  1. If _flags_ contains `"u"`, let _fullUnicode_ be *true*.
  1. Else, let _fullUnicode_ be *false*.
  1. Repeat,
    1. Let _match_ be ? RegExpExec(_matcher_, _S_).
    1. If _match_ is *null*, return *undefined*.
    1. If _global_ is *true*, then
      1. Let _matchStr_ be ? ToString(? Get(_match_, *"0"*)).
      1. If _matchStr_ is the empty string, then
        1. Let _thisIndex_ be ? ToLength(? Get(_matcher_, *"lastIndex"*)).
        1. Let _nextIndex_ be ! AdvanceStringIndex(_S_, _thisIndex_, _fullUnicode_).
        1. Perform ? Set(_matcher_, *"lastIndex"*, ).
      1. Perform ? Yield(_match_).
    1. Else,
      1. Perform ? Yield(_match_).
      1. Return *undefined*.
</emu-alg>
@devsnek

This comment has been minimized.

Copy link
Member Author

commented Aug 12, 2019

Actually, we might need to add a GeneratorResume before Return _generator_. to allow the generator to have an initial time to do things like check its argument types. The steps of a builtin function would Yield() once after initialization. Alternatively, we could split the steps into a "prelude" and "body" where the prelude is eagerly evaluated, and the body is evaluated in the generator context.

@ljharb

This comment has been minimized.

Copy link
Member

commented Aug 12, 2019

Why couldn't we do it now? The only observable part is the toString's native code, which wouldn't change.

@devsnek

This comment has been minimized.

Copy link
Member Author

commented Aug 12, 2019

@ljharb because RegExpStringIteratorPrototype is observable, we can't stop having the function return it.

@ljharb

This comment has been minimized.

Copy link
Member

commented Aug 12, 2019

ahhh right, so to make this PR maximally useful, we'd have to have a way to control the [[Prototype]] of the returned iterator (since we'd want to use this approach on all the iterators in the spec, i'd think)

devsnek added some commits Aug 12, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.