Programmatically convert synchronous code to asynchronous code

2.8k Views Asked by At

I am writing a parser for a metalanguage to be run in the browser. The metalanguage is blocking, but needs to be converted to nonblocking in the interpreter due to the limitations of javascript.

For example, the metalanguage code might look something like

1. dosomething(4)
2. dosomethingelse(1)
3. dosomething(7)
4. goto 2

with the functions implemented in javascript as

function dosomething(n, callback) {
  ... // do something with n
  setTimeout(callback, 1000);
}

function dosomethingelse(n, callback) {
  ... // do something else with n
  setTimeout(callback, 1000);
}

Without the goto statements, this would be easy to compile to javascript and then eval. However, I have no clue how to implement the gotos. Any help is appreciated.

2

There are 2 best solutions below

0
On

As others have said, check out Promises. This tutorial really helped me out for getting started with them, hopefully it helps you too. https://spring.io/understanding/javascript-promises

0
On

Use yield to make functions you can pause and then regenerator to run it in older browsers:

First, we convert dosomething(4) in your language into:

function doSomething(n, callback){
    setTimeout(function(){ callback(null,true); }, n);
}

Note the node err-back convention - callbacks take two arguments - the first is an error and the second is the return value.

Then - you can convert them to promises easily:

var doSomething = Promise.promisify(doSomething); // using bluebird.

Now, when they return promises- you can wrap lines with yields:

Promise.coroutine(function*(){ 
    yield dosomething(4);
    yield dosomethingelse(1);
    yield dosomething(7);
});

You will need to call addYieldHandler in order to deal with yielded non-promise values. This will execute them "synchronously" waiting for each promise to resolve before starting the next. Finally use regenerator to convert your code into something ES5 browsers can run (Since yield only works in FF and in Chrome under a flag atm).