mitranim/jisp

Execution order control

Opened this issue · 0 comments

Many jisp expressions translate into multi-line chunks of JavaScript that aren't valid expressions. Jisp works around this by assigning results of multi-line expressions to reference variables and putting those variables into JS expressions. If the expression is a conditional, this can cause the hoisted multi-line code to be executed out of order, or be executed when it’s not supposed to.

Example.

Jisp source:

(= x 0)
(and false (for i `(1 2 3) (+= x i)))

Compiled JavaScript:

var x, i, _i, _res, _ref;
x = 0;
_res = [];
_ref = [1, 2, 3];
for (_i = 0; _i < _ref.length; ++_i) {
  i = _ref[_i];
  _res.push((x += i));
}
false && _res;

The loop is not supposed to be executed, yet it does, with unintended side effects. Similarly, things can be executed out of order.

One possible solution is to wrap hoisted blocks into self-executing lambdas with references as return values instead of hoisting them. Functions in JavaScript are expressions that are allowed to be multiline, so this sounds like an easy solution. Another possible solution is to wrap them into non-self-executing lambdas assigned to references, and embed references as function calls rather than values. This should produce more readable code than blunt function embedding, at the cost of more variable bindings in the code.

For prettier output, we should also check if a multi-line block consists purely of native JS expressions. In this case, we should compile it to a grouped (in parentheses) list separated with commas.