coffee-subscript
Version:
Integration between CoffeeScript and arbitrary DSL-s that compile to JavaScript
148 lines (139 loc) • 4.47 kB
JavaScript
// Generated by CoffeeScript 1.6.2
(function() {
var CoffeeScript;
CoffeeScript = require('coffee-script');
exports.preprocess = function(mixedCode, opts) {
var ast, char, coffeeCode, escape, fragments, i, inQuote, indent, indentRE, j, k, lines, max, parens, queue, scopeNode, squiggleStart, startPos, stopPos, _i, _ref;
if (opts == null) {
opts = {};
}
fragments = [];
mixedCode = mixedCode.replace(/«([^»]*)»/g, function(_, dslCode) {
var padding;
fragments.push({
kind: 'expression',
dslCode: dslCode
});
padding = dslCode.replace(/[^\n]/g, '');
return "`@" + (fragments.length - 1) + padding + "`";
});
lines = mixedCode.split('\n');
i = 0;
while (i < lines.length) {
if (/\(\s*~>.*\)/.test(lines[i])) {
while ((squiggleStart = lines[i].indexOf("~>")) !== -1) {
startPos = squiggleStart;
while (startPos > 0) {
startPos--;
if (lines[i][startPos] === "(") {
break;
}
}
max = lines[i].length - 1;
escape = false;
inQuote = false;
parens = 1;
stopPos = squiggleStart + 1;
while (parens) {
stopPos++;
if (stopPos > max) {
throw "Did not match paren";
}
char = lines[i][stopPos];
if (inQuote) {
if (escape) {
escape = false;
} else if (char === "\\") {
escape = true;
} else if (char === '"') {
inQuote = false;
}
} else if (char === '"') {
inQuote = true;
} else if (char === "(") {
parens++;
} else if (char === ")") {
parens--;
}
}
fragments.push({
kind: 'function',
dslCode: lines[i].slice(squiggleStart + 2, +(stopPos - 1) + 1 || 9e9)
});
lines[i] = lines[i].replace(lines[i].slice(startPos, +stopPos + 1 || 9e9), "`@" + (fragments.length - 1) + "`");
}
i++;
} else if (/~>\s*$/.test(lines[i])) {
indent = lines[i].replace(/^([ \t]*).*$/, '$1');
indentRE = new RegExp('^' + indent.replace(/\t/g, '\\t') + '[ \t]');
j = i + 1;
while (j < lines.length && indentRE.test(lines[j])) {
j++;
}
fragments.push({
kind: 'function',
dslCode: lines.slice(i + 1, j).join('\n')
});
lines[i] = lines[i].replace(/~>\s*$/, "`@" + (fragments.length - 1) + "`");
for (k = _i = _ref = i + 1; _i < j; k = _i += 1) {
lines[k] = '';
}
i = j;
} else {
i++;
}
}
coffeeCode = lines.join('\n');
ast = CoffeeScript.nodes(coffeeCode);
ast.vars = {};
queue = [ast];
while (queue.length) {
scopeNode = queue.shift();
scopeNode.traverseChildren(false, function(node) {
var m, name, v, _ref1, _ref2, _ref3;
name = node.constructor.name;
if (name === 'Code') {
node.vars = {};
_ref1 = scopeNode.vars;
for (k in _ref1) {
v = _ref1[k];
node.vars[k] = v;
}
queue.push(node);
} else if (name === 'Literal' && (m = node.value.match(/^@(\d+)$/))) {
fragments[+m[1]].vars = scopeNode.vars;
} else if (name === 'Assign') {
if (v = (_ref2 = node.variable) != null ? (_ref3 = _ref2.base) != null ? _ref3.value : void 0 : void 0) {
scopeNode.vars[v] = {};
}
}
return true;
});
}
return coffeeCode = coffeeCode.replace(/`@(\d+)`/g, function(_, id) {
var f, jsCode, name, _ref1;
f = fragments[+id];
jsCode = require((_ref1 = opts.dsl) != null ? _ref1 : 'apl').compile(f.dslCode, {
embedded: true,
kind: f.kind,
vars: (function() {
var _ref1, _results;
_ref1 = f.vars;
_results = [];
for (name in _ref1) {
_ = _ref1[name];
_results.push({
name: name
});
}
return _results;
})()
});
jsCode = "(function () { " + jsCode + " })";
if (f.kind === 'expression') {
jsCode += '()';
}
return "`" + jsCode + "`";
});
};
}).call(this);