DanielXMoore / Civet

A TypeScript superset that favors more types and less typing
https://civet.dev
MIT License
1.33k stars 28 forks source link

Eliminating `return` after `loop` in some cases #1161

Closed bbrk24 closed 2 months ago

bbrk24 commented 2 months ago

When writing an infinite generator, such as the below, Civet emits an unreachable return statement:

f := (a, b) ->
 yield a
 loop
   yield b
   [a, b] = [b, a + b]
const f = function* (a, b) {
  yield a;
  const results = [];
  while (true) {
    yield b;
    results.push(([a, b] = [b, a + b]));
  }
  return results;
};

While this could be removed, there are some things we have to be careful of:

STRd6 commented 2 months ago

Adding a void type annotation to the function or a trailing ; will omit the implicit return.

f := (a, b): void ->
  yield a
  loop
    yield b
    [a, b] = [b, a + b]
f := (a, b) ->
  yield a
  loop
    yield b
    [a, b] = [b, a + b]
  ;

We may be able to omit the return in this simple case but probably not generally.

edemaine commented 2 months ago

Does ESLint complain about the inaccessible return in this case? We could try to mimic their algorithm for conservative unreachability testing, to avoid warnings. But I imagine you were concerned more about efficiency, for which I think Daniel's response is the right one.

bbrk24 commented 2 months ago

Not just ESLint, even TypeScript complains about it: https://www.typescriptlang.org/play?#code/MYewdgzgLgBAZjAvPArmYUCW4BUMAUAhgDQwBGAlDAN4CwAUDDAJ6YCmANgCYyEDcDJqEiwATmwgoOUCEhgBtALoDGMAO4ALTBzYEoolGyp1VTVpx5kVTJuMnSIAOgAOKCBvz55JcornyyUkIYAGpfCgprGABfQRhxKBRRMHiJKRkVaL4gA