use of org.mozilla.javascript.ast.Scope in project hackpad by dropbox.
the class NodeTransformer method visitLet.
protected Node visitLet(boolean createWith, Node parent, Node previous, Node scopeNode) {
Node vars = scopeNode.getFirstChild();
Node body = vars.getNext();
scopeNode.removeChild(vars);
scopeNode.removeChild(body);
boolean isExpression = scopeNode.getType() == Token.LETEXPR;
Node result;
Node newVars;
if (createWith) {
result = new Node(isExpression ? Token.WITHEXPR : Token.BLOCK);
result = replaceCurrent(parent, previous, scopeNode, result);
ArrayList<Object> list = new ArrayList<Object>();
Node objectLiteral = new Node(Token.OBJECTLIT);
for (Node v = vars.getFirstChild(); v != null; v = v.getNext()) {
Node current = v;
if (current.getType() == Token.LETEXPR) {
// destructuring in let expr, e.g. let ([x, y] = [3, 4]) {}
List<?> destructuringNames = (List<?>) current.getProp(Node.DESTRUCTURING_NAMES);
Node c = current.getFirstChild();
if (c.getType() != Token.LET)
throw Kit.codeBug();
// Add initialization code to front of body
if (isExpression) {
body = new Node(Token.COMMA, c.getNext(), body);
} else {
body = new Node(Token.BLOCK, new Node(Token.EXPR_VOID, c.getNext()), body);
}
// defined in the destructuring assignment
if (destructuringNames != null) {
list.addAll(destructuringNames);
for (int i = 0; i < destructuringNames.size(); i++) {
objectLiteral.addChildToBack(new Node(Token.VOID, Node.newNumber(0.0)));
}
}
// should be a NAME, checked below
current = c.getFirstChild();
}
if (current.getType() != Token.NAME)
throw Kit.codeBug();
list.add(ScriptRuntime.getIndexObject(current.getString()));
Node init = current.getFirstChild();
if (init == null) {
init = new Node(Token.VOID, Node.newNumber(0.0));
}
objectLiteral.addChildToBack(init);
}
objectLiteral.putProp(Node.OBJECT_IDS_PROP, list.toArray());
newVars = new Node(Token.ENTERWITH, objectLiteral);
result.addChildToBack(newVars);
result.addChildToBack(new Node(Token.WITH, body));
result.addChildToBack(new Node(Token.LEAVEWITH));
} else {
result = new Node(isExpression ? Token.COMMA : Token.BLOCK);
result = replaceCurrent(parent, previous, scopeNode, result);
newVars = new Node(Token.COMMA);
for (Node v = vars.getFirstChild(); v != null; v = v.getNext()) {
Node current = v;
if (current.getType() == Token.LETEXPR) {
// destructuring in let expr, e.g. let ([x, y] = [3, 4]) {}
Node c = current.getFirstChild();
if (c.getType() != Token.LET)
throw Kit.codeBug();
// Add initialization code to front of body
if (isExpression) {
body = new Node(Token.COMMA, c.getNext(), body);
} else {
body = new Node(Token.BLOCK, new Node(Token.EXPR_VOID, c.getNext()), body);
}
// We're removing the LETEXPR, so move the symbols
Scope.joinScopes((Scope) current, (Scope) scopeNode);
// should be a NAME, checked below
current = c.getFirstChild();
}
if (current.getType() != Token.NAME)
throw Kit.codeBug();
Node stringNode = Node.newString(current.getString());
stringNode.setScope((Scope) scopeNode);
Node init = current.getFirstChild();
if (init == null) {
init = new Node(Token.VOID, Node.newNumber(0.0));
}
newVars.addChildToBack(new Node(Token.SETVAR, stringNode, init));
}
if (isExpression) {
result.addChildToBack(newVars);
scopeNode.setType(Token.COMMA);
result.addChildToBack(scopeNode);
scopeNode.addChildToBack(body);
if (body instanceof Scope) {
Scope scopeParent = ((Scope) body).getParentScope();
((Scope) body).setParentScope((Scope) scopeNode);
((Scope) scopeNode).setParentScope(scopeParent);
}
} else {
result.addChildToBack(new Node(Token.EXPR_VOID, newVars));
scopeNode.setType(Token.BLOCK);
result.addChildToBack(scopeNode);
scopeNode.addChildrenToBack(body);
if (body instanceof Scope) {
Scope scopeParent = ((Scope) body).getParentScope();
((Scope) body).setParentScope((Scope) scopeNode);
((Scope) scopeNode).setParentScope(scopeParent);
}
}
}
return result;
}
use of org.mozilla.javascript.ast.Scope in project HL4A by HL4A.
the class IRFactory method transformBlock.
private Node transformBlock(AstNode node) {
if (node instanceof Scope) {
pushScope((Scope) node);
}
try {
List<Node> kids = new ArrayList<Node>();
for (Node kid : node) {
kids.add(transform((AstNode) kid));
}
node.removeChildren();
for (Node kid : kids) {
node.addChildToBack(kid);
}
return node;
} finally {
if (node instanceof Scope) {
popScope();
}
}
}
use of org.mozilla.javascript.ast.Scope in project HL4A by HL4A.
the class IRFactory method arrayCompTransformHelper.
private Node arrayCompTransformHelper(ArrayComprehension node, String arrayName) {
decompiler.addToken(Token.LB);
int lineno = node.getLineno();
Node expr = transform(node.getResult());
List<ArrayComprehensionLoop> loops = node.getLoops();
int numLoops = loops.size();
// Walk through loops, collecting and defining their iterator symbols.
Node[] iterators = new Node[numLoops];
Node[] iteratedObjs = new Node[numLoops];
for (int i = 0; i < numLoops; i++) {
ArrayComprehensionLoop acl = loops.get(i);
decompiler.addName(" ");
decompiler.addToken(Token.FOR);
if (acl.isForEach()) {
decompiler.addName("each ");
}
decompiler.addToken(Token.LP);
AstNode iter = acl.getIterator();
String name = null;
if (iter.getType() == Token.NAME) {
name = iter.getString();
decompiler.addName(name);
} else {
// destructuring assignment
decompile(iter);
name = currentScriptOrFn.getNextTempName();
defineSymbol(Token.LP, name, false);
expr = createBinary(Token.COMMA, createAssignment(Token.ASSIGN, iter, createName(name)), expr);
}
Node init = createName(name);
// Define as a let since we want the scope of the variable to
// be restricted to the array comprehension
defineSymbol(Token.LET, name, false);
iterators[i] = init;
if (acl.isForOf()) {
decompiler.addName("of ");
} else {
decompiler.addToken(Token.IN);
}
iteratedObjs[i] = transform(acl.getIteratedObject());
decompiler.addToken(Token.RP);
}
// generate code for tmpArray.push(body)
Node call = createCallOrNew(Token.CALL, createPropertyGet(createName(arrayName), null, "push", 0));
Node body = new Node(Token.EXPR_VOID, call, lineno);
if (node.getFilter() != null) {
decompiler.addName(" ");
decompiler.addToken(Token.IF);
decompiler.addToken(Token.LP);
body = createIf(transform(node.getFilter()), body, null, lineno);
decompiler.addToken(Token.RP);
}
// Now walk loops in reverse to build up the body statement.
int pushed = 0;
try {
for (int i = numLoops - 1; i >= 0; i--) {
ArrayComprehensionLoop acl = loops.get(i);
Scope loop = createLoopNode(// no label
null, acl.getLineno());
pushScope(loop);
pushed++;
body = createForIn(Token.LET, loop, iterators[i], iteratedObjs[i], body, acl.isForEach(), acl.isForOf());
}
} finally {
for (int i = 0; i < pushed; i++) {
popScope();
}
}
decompiler.addToken(Token.RB);
// Now that we've accumulated any destructuring forms,
// add expr to the call node; it's pushed on each iteration.
call.addChildToBack(expr);
return body;
}
use of org.mozilla.javascript.ast.Scope in project HL4A by HL4A.
the class IRFactory method transformArrayComp.
private Node transformArrayComp(ArrayComprehension node) {
// An array comprehension expression such as
//
// [expr for (x in foo) for each ([y, z] in bar) if (cond)]
//
// is rewritten approximately as
//
// new Scope(ARRAYCOMP) {
// new Node(BLOCK) {
// let tmp1 = new Array;
// for (let x in foo) {
// for each (let tmp2 in bar) {
// if (cond) {
// tmp1.push([y, z] = tmp2, expr);
// }
// }
// }
// }
// createName(tmp1)
// }
int lineno = node.getLineno();
Scope scopeNode = createScopeNode(Token.ARRAYCOMP, lineno);
String arrayName = currentScriptOrFn.getNextTempName();
pushScope(scopeNode);
try {
defineSymbol(Token.LET, arrayName, false);
Node block = new Node(Token.BLOCK, lineno);
Node newArray = createCallOrNew(Token.NEW, createName("Array"));
Node init = new Node(Token.EXPR_VOID, createAssignment(Token.ASSIGN, createName(arrayName), newArray), lineno);
block.addChildToBack(init);
block.addChildToBack(arrayCompTransformHelper(node, arrayName));
scopeNode.addChildToBack(block);
scopeNode.addChildToBack(createName(arrayName));
return scopeNode;
} finally {
popScope();
}
}
use of org.mozilla.javascript.ast.Scope in project HL4A by HL4A.
the class IRFactory method genExprTransformHelper.
private Node genExprTransformHelper(GeneratorExpression node) {
decompiler.addToken(Token.LP);
int lineno = node.getLineno();
Node expr = transform(node.getResult());
List<GeneratorExpressionLoop> loops = node.getLoops();
int numLoops = loops.size();
// Walk through loops, collecting and defining their iterator symbols.
Node[] iterators = new Node[numLoops];
Node[] iteratedObjs = new Node[numLoops];
for (int i = 0; i < numLoops; i++) {
GeneratorExpressionLoop acl = loops.get(i);
decompiler.addName(" ");
decompiler.addToken(Token.FOR);
decompiler.addToken(Token.LP);
AstNode iter = acl.getIterator();
String name = null;
if (iter.getType() == Token.NAME) {
name = iter.getString();
decompiler.addName(name);
} else {
// destructuring assignment
decompile(iter);
name = currentScriptOrFn.getNextTempName();
defineSymbol(Token.LP, name, false);
expr = createBinary(Token.COMMA, createAssignment(Token.ASSIGN, iter, createName(name)), expr);
}
Node init = createName(name);
// Define as a let since we want the scope of the variable to
// be restricted to the array comprehension
defineSymbol(Token.LET, name, false);
iterators[i] = init;
if (acl.isForOf()) {
decompiler.addName("of ");
} else {
decompiler.addToken(Token.IN);
}
iteratedObjs[i] = transform(acl.getIteratedObject());
decompiler.addToken(Token.RP);
}
// generate code for tmpArray.push(body)
Node yield = new Node(Token.YIELD, expr, node.getLineno());
Node body = new Node(Token.EXPR_VOID, yield, lineno);
if (node.getFilter() != null) {
decompiler.addName(" ");
decompiler.addToken(Token.IF);
decompiler.addToken(Token.LP);
body = createIf(transform(node.getFilter()), body, null, lineno);
decompiler.addToken(Token.RP);
}
// Now walk loops in reverse to build up the body statement.
int pushed = 0;
try {
for (int i = numLoops - 1; i >= 0; i--) {
GeneratorExpressionLoop acl = loops.get(i);
Scope loop = createLoopNode(// no label
null, acl.getLineno());
pushScope(loop);
pushed++;
body = createForIn(Token.LET, loop, iterators[i], iteratedObjs[i], body, acl.isForEach(), acl.isForOf());
}
} finally {
for (int i = 0; i < pushed; i++) {
popScope();
}
}
decompiler.addToken(Token.RP);
return body;
}
Aggregations