ckknight / gorillascript

GorillaScript is a compile-to-JavaScript language designed to empower the user while attempting to prevent some common errors.
MIT License
300 stars 34 forks source link

yield in try - else/finally #154

Closed kkirby closed 9 years ago

kkirby commented 9 years ago

Hello.

I was trying to use a yield in a try's else statement and I got an error saying that I cannot use yield. I looked into the parser's code to see if I could come up with a quick fix, but I wasn't able to. My idea was to have the parser treat the finally node as a new promise generator and then return the result to the parent generator.

So instead of:

_finallies.pop()();
++_state;

It would be

++_state;
return { done: false, value: _finallies.pop()() };

My problem with implementing this was I have no idea how I would translate the node to to become a generator node. I saw that I might need to manipulate the scope's stack and put in-generator as true, but I'm not really sure. The next battle would be to translate the generator to a promise.

Any ideas?

vendethiel commented 9 years ago

(I really think gorilla should compile to es6-style yield...)

kkirby commented 9 years ago

@vendethiel, there is an issue open for that: #26

vendethiel commented 9 years ago

Right. Somebody needs to step up and implement it I guess, then :).

kkirby commented 9 years ago

This has been fixed in my community repo

kkirby commented 9 years ago

@vendethiel My repo now has gorillascript compiling to native es6-style yields. The output of this:

#(items)**
    try
        yield asdf()
    catch e
        doSomething()
    finally
        yield abc()

Is:

(function () {
  "use strict";
  var __generatorToPromise;
  __generatorToPromise = function (func) {
    function res(iter) {
      return new Promise(function (fulfill, reject) {
        function next(result, handler) {
          var info;
          if (handler == null) {
            handler = "next";
          }
          try {
            info = iter[handler](result);
          } catch (e) {
            return reject(e);
          }
          if (info.done) {
            return fulfill(info.value);
          } else if (info.value instanceof Promise) {
            return info.value.then(
              function (result) {
                return next(result);
              },
              function (e) {
                return next(e, "throw");
              }
            );
          } else {
            return next(info.value);
          }
        }
        return next();
      });
    }
    if (typeof func !== "function" && func.next != null) {
      return res(func);
    } else {
      return function () {
        return res(func.apply(this, arguments));
      };
    }
  };
  __generatorToPromise(function *(items) {
    try {
      return yield asdf();
    } catch (e) {
      return doSomething();
    } finally {
      yield abc();
    }
  });
}.call(this));