Skip to content

Commit

Permalink
refactor: remove the biggest parts of the former expression parsing a…
Browse files Browse the repository at this point in the history
…lgorithm

Closes #296
  • Loading branch information
PK1A committed Sep 17, 2014
1 parent 8aea84a commit aa6a7b2
Show file tree
Hide file tree
Showing 2 changed files with 4 additions and 696 deletions.
149 changes: 1 addition & 148 deletions hsp/compiler/jsgenerator/processors.js
Expand Up @@ -342,157 +342,10 @@ exports["cptattribute"] = function (node, walker) {
*/
function formatExpression (expression, firstIndex, walker) {
var category = expression.category, codeStmts, code = '', nextIndex = firstIndex;
var bound = (expression.bound === false) ? 0 : 1;
var exprIndex = firstIndex;
var expAst;
if (category === 'objectref' || category === 'functionref') {
var path = expression.path, argExprs = null, argExprIndex = null, args = expression.args;
if (path.length === 0) {
walker.logError("Expression path cannot be empty");
} else {
var root = path[0], isRootInScope = walker.isInScope(root);
/* Possible expression types are:
* 0: unbound data ref - e.g. {e1:[0,1,"item_key"]}
* 1: bound data ref - e.g. {e1:[1,2,"person","name"]}
* 2: literal data ref - e.g. {e1:[2,2,person,"name"]}
* 3: function call - e.g. {e1:[3,2,"ctl","deleteItem",1,2,1,0]}
* 4: function call literal- e.g. {e1:[4,1,myfunc,1,2,1,0]}
* 5: literal value - e.g. {e1:[5,"some value"]}
* 6: function expression - e.g. {e1:[6,function(a0,a1){return a0+a1;},2,3]}*/
var exprType = isRootInScope ? bound : 2;
if (root === "event") {
exprType = 0;
}

if (exprType === 2) {
// root is a global reference
walker.addGlobalRef(root);
root = "_" + root;
path[0] = "_" + path[0];
}

if (category === 'functionref') {
exprType = isRootInScope ? 3 : 4;
argExprs = [];
argExprIndex = [];
var arg, argCategory, expr, index = exprIndex + 1;
for (var i = 0; i < args.length; i++) {
arg = args[i];
argCategory = arg.category;
if (argCategory === "string" || argCategory === "boolean" || argCategory === "number") {
continue;
}
expr = formatExpression(arg, index, walker);
argExprs.push(expr.code);
argExprIndex[i] = expr.exprIdx;
index = expr.nextIndex;
}
nextIndex = index;
} else {
nextIndex++;
}

var result, rootRef = path[0];
if (isRootInScope || root === "event") {
rootRef = '"' + rootRef + '"';
}
var pathLength = path.length;

var generatedPath = [], pathItem;
generatedPath.push(rootRef);
for (var i = 1; i < pathLength; i++) {
pathItem = path[i];
if ((typeof pathItem) === "string") {
generatedPath.push('"' + pathItem + '"');
} else {
generatedPath.push(pathItem);
}
}
result = ['e', exprIndex, ':[', exprType, ',', pathLength, ',', generatedPath.join(',')];


if (args && args.length > 0) {
var argCategory, arg;
for (var i = 0; i < args.length; i++) {
arg = args[i];
argCategory = arg.category;
if (argCategory === "string") {
result.push(',0,"' + escapeNewLines(arg.value.replace(/"/g, "\\\"")) + '"');
} else if (argCategory === "boolean" || argCategory === "number") {
result.push(',0,' + arg.value);
} else {
// this is not a literal
result.push(',1,' + argExprIndex[i]);
}
}
if (argExprs && argExprs.length > 0) {
result.push("],");
result.push(argExprs.join(","));
} else {
result.push("]");
}

} else {
result.push("]");
}
code = result.join("");
}

} else if (category === 'boolean' || category === 'number') {
code = ['e', exprIndex, ':[5,', expression.value, ']'].join('');
nextIndex++;
} else if (category === 'string') {
code = ['e', exprIndex, ':[5,"', ('' + expression.value).replace(/"/g, "\\\""), '"]'].join('');
nextIndex++;
} else if (category === 'jsexpression' || category === 'dynref') {
var refs = expression.objectrefs, ref, expr, index = exprIndex + 1, codefragments=[], exprs = [], exprIdxs = [];

if (category === 'jsexpression' && refs === undefined) {
console.warn("[formatExpression] The following expression has not been pre-processed - parser should be updated: ");
console.dir(expression);
}
var args = [], length=0, argSeparator = (length > 0) ? ',' : '';
if (refs) {
// this is the root expression
length = refs.length;
for (var i = 0; length > i; i++) {
ref = refs[i];
if (ref.category === "dynref") {
// pass the args and expressions to the dynref expression
ref.args=args;
ref.exprIdxs=exprIdxs;
}
expr = formatExpression(ref, index, walker);
args[i] = "a" + i;
exprs.push(expr);
codefragments.push(expr.code);
exprIdxs[i] = expr.exprIdx;
index = expr.nextIndex;
}
} else if (expression.args || expression.exprIdxs) {
args=expression.args;
exprIdxs=expression.exprIdxs;
}

var func,code0;
argSeparator = (exprIdxs.length > 0) ? ',' : '';
if (category==='jsexpression') {
func = ['function(', args.join(','), ') {return ', expression.code, ';}'].join('');
code0 = ['e', exprIndex, ':[6,', func, argSeparator, exprIdxs.join(','), ']'].join('');
} else {
// category === 'dynref'
var cf = expression.codefragments;
if (cf.length === 0) {
walker.logError("Expression code fragments cannot be empty");
}
func = ['function(i', argSeparator, args.join(','), ') {return [', cf.join(','), '][i];}'].join('');
code0 = ['e', exprIndex, ':[7,',cf.length,',', func, argSeparator, exprIdxs.join(','), ']'].join('');

}
codefragments.splice(0, 0, code0);
code = codefragments.join(',');
nextIndex = index;
} else if (category === 'jsexptext') {
if (category === 'jsexptext') {
//compile the expression to detect errors and parse-out identifiers
try {
expAst = exParser(expression.value);
Expand Down

0 comments on commit aa6a7b2

Please sign in to comment.