use of org.mozilla.javascript.ast.Jump in project HL4A by HL4A.
the class IRFactory method addSwitchCase.
/**
* If caseExpression argument is null it indicates a default label.
*/
private void addSwitchCase(Node switchBlock, Node caseExpression, Node statements) {
if (switchBlock.getType() != Token.BLOCK)
throw Kit.codeBug();
Jump switchNode = (Jump) switchBlock.getFirstChild();
if (switchNode.getType() != Token.SWITCH)
throw Kit.codeBug();
Node gotoTarget = Node.newTarget();
if (caseExpression != null) {
Jump caseNode = new Jump(Token.CASE, caseExpression);
caseNode.target = gotoTarget;
switchNode.addChildToBack(caseNode);
} else {
switchNode.setDefault(gotoTarget);
}
switchBlock.addChildToBack(gotoTarget);
switchBlock.addChildToBack(statements);
}
use of org.mozilla.javascript.ast.Jump in project HL4A by HL4A.
the class IRFactory method createForIn.
/**
* Generate IR for a for..in loop.
*/
private Node createForIn(int declType, Node loop, Node lhs, Node obj, Node body, boolean isForEach, boolean isForOf) {
int destructuring = -1;
int destructuringLen = 0;
Node lvalue;
int type = lhs.getType();
if (type == Token.VAR || type == Token.LET) {
Node kid = lhs.getLastChild();
int kidType = kid.getType();
if (kidType == Token.ARRAYLIT || kidType == Token.OBJECTLIT) {
type = destructuring = kidType;
lvalue = kid;
destructuringLen = 0;
if (kid instanceof ArrayLiteral)
destructuringLen = ((ArrayLiteral) kid).getDestructuringLength();
} else if (kidType == Token.NAME) {
lvalue = Node.newString(Token.NAME, kid.getString());
} else {
reportError("msg.bad.for.in.lhs");
return null;
}
} else if (type == Token.ARRAYLIT || type == Token.OBJECTLIT) {
destructuring = type;
lvalue = lhs;
destructuringLen = 0;
if (lhs instanceof ArrayLiteral)
destructuringLen = ((ArrayLiteral) lhs).getDestructuringLength();
} else {
lvalue = makeReference(lhs);
if (lvalue == null) {
reportError("msg.bad.for.in.lhs");
return null;
}
}
Node localBlock = new Node(Token.LOCAL_BLOCK);
int initType = isForEach ? Token.ENUM_INIT_VALUES : isForOf ? Token.ENUM_INIT_VALUES_IN_ORDER : (destructuring != -1 ? Token.ENUM_INIT_ARRAY : Token.ENUM_INIT_KEYS);
Node init = new Node(initType, obj);
init.putProp(Node.LOCAL_BLOCK_PROP, localBlock);
Node cond = new Node(Token.ENUM_NEXT);
cond.putProp(Node.LOCAL_BLOCK_PROP, localBlock);
Node id = new Node(Token.ENUM_ID);
id.putProp(Node.LOCAL_BLOCK_PROP, localBlock);
Node newBody = new Node(Token.BLOCK);
Node assign;
if (destructuring != -1) {
assign = createDestructuringAssignment(declType, lvalue, id);
if (!isForEach && !isForOf && (destructuring == Token.OBJECTLIT || destructuringLen != 2)) {
// destructuring assignment is only allowed in for..each or
// with an array type of length 2 (to hold key and value)
reportError("msg.bad.for.in.destruct");
}
} else {
assign = simpleAssignment(lvalue, id);
}
newBody.addChildToBack(new Node(Token.EXPR_VOID, assign));
newBody.addChildToBack(body);
loop = createLoop((Jump) loop, LOOP_WHILE, newBody, cond, null, null);
loop.addChildToFront(init);
if (type == Token.VAR || type == Token.LET)
loop.addChildToFront(lhs);
localBlock.addChildToBack(loop);
return localBlock;
}
use of org.mozilla.javascript.ast.Jump in project HL4A by HL4A.
the class IRFactory method createTryCatchFinally.
/**
* Try/Catch/Finally
*
* The IRFactory tries to express as much as possible in the tree;
* the responsibilities remaining for Codegen are to add the Java
* handlers: (Either (but not both) of TARGET and FINALLY might not
* be defined)
*
* - a catch handler for javascript exceptions that unwraps the
* exception onto the stack and GOTOes to the catch target
*
* - a finally handler
*
* ... and a goto to GOTO around these handlers.
*/
private Node createTryCatchFinally(Node tryBlock, Node catchBlocks, Node finallyBlock, int lineno) {
boolean hasFinally = (finallyBlock != null) && (finallyBlock.getType() != Token.BLOCK || finallyBlock.hasChildren());
// short circuit
if (tryBlock.getType() == Token.BLOCK && !tryBlock.hasChildren() && !hasFinally) {
return tryBlock;
}
boolean hasCatch = catchBlocks.hasChildren();
// short circuit
if (!hasFinally && !hasCatch) {
// bc finally might be an empty block...
return tryBlock;
}
Node handlerBlock = new Node(Token.LOCAL_BLOCK);
Jump pn = new Jump(Token.TRY, tryBlock, lineno);
pn.putProp(Node.LOCAL_BLOCK_PROP, handlerBlock);
if (hasCatch) {
// jump around catch code
Node endCatch = Node.newTarget();
pn.addChildToBack(makeJump(Token.GOTO, endCatch));
// make a TARGET for the catch that the tcf node knows about
Node catchTarget = Node.newTarget();
pn.target = catchTarget;
// mark it
pn.addChildToBack(catchTarget);
//
// Given
//
// try {
// tryBlock;
// } catch (e if condition1) {
// something1;
// ...
//
// } catch (e if conditionN) {
// somethingN;
// } catch (e) {
// somethingDefault;
// }
//
// rewrite as
//
// try {
// tryBlock;
// goto after_catch:
// } catch (x) {
// with (newCatchScope(e, x)) {
// if (condition1) {
// something1;
// goto after_catch;
// }
// }
// ...
// with (newCatchScope(e, x)) {
// if (conditionN) {
// somethingN;
// goto after_catch;
// }
// }
// with (newCatchScope(e, x)) {
// somethingDefault;
// goto after_catch;
// }
// }
// after_catch:
//
// If there is no default catch, then the last with block
// arround "somethingDefault;" is replaced by "rethrow;"
// It is assumed that catch handler generation will store
// exeception object in handlerBlock register
// Block with local for exception scope objects
Node catchScopeBlock = new Node(Token.LOCAL_BLOCK);
// expects catchblocks children to be (cond block) pairs.
Node cb = catchBlocks.getFirstChild();
boolean hasDefault = false;
int scopeIndex = 0;
while (cb != null) {
int catchLineNo = cb.getLineno();
Node name = cb.getFirstChild();
Node cond = name.getNext();
Node catchStatement = cond.getNext();
cb.removeChild(name);
cb.removeChild(cond);
cb.removeChild(catchStatement);
// Add goto to the catch statement to jump out of catch
// but prefix it with LEAVEWITH since try..catch produces
// "with"code in order to limit the scope of the exception
// object.
catchStatement.addChildToBack(new Node(Token.LEAVEWITH));
catchStatement.addChildToBack(makeJump(Token.GOTO, endCatch));
// Create condition "if" when present
Node condStmt;
if (cond.getType() == Token.EMPTY) {
condStmt = catchStatement;
hasDefault = true;
} else {
condStmt = createIf(cond, catchStatement, null, catchLineNo);
}
// Generate code to create the scope object and store
// it in catchScopeBlock register
Node catchScope = new Node(Token.CATCH_SCOPE, name, createUseLocal(handlerBlock));
catchScope.putProp(Node.LOCAL_BLOCK_PROP, catchScopeBlock);
catchScope.putIntProp(Node.CATCH_SCOPE_PROP, scopeIndex);
catchScopeBlock.addChildToBack(catchScope);
// Add with statement based on catch scope object
catchScopeBlock.addChildToBack(createWith(createUseLocal(catchScopeBlock), condStmt, catchLineNo));
// move to next cb
cb = cb.getNext();
++scopeIndex;
}
pn.addChildToBack(catchScopeBlock);
if (!hasDefault) {
// Generate code to rethrow if no catch clause was executed
Node rethrow = new Node(Token.RETHROW);
rethrow.putProp(Node.LOCAL_BLOCK_PROP, handlerBlock);
pn.addChildToBack(rethrow);
}
pn.addChildToBack(endCatch);
}
if (hasFinally) {
Node finallyTarget = Node.newTarget();
pn.setFinally(finallyTarget);
// add jsr finally to the try block
pn.addChildToBack(makeJump(Token.JSR, finallyTarget));
// jump around finally code
Node finallyEnd = Node.newTarget();
pn.addChildToBack(makeJump(Token.GOTO, finallyEnd));
pn.addChildToBack(finallyTarget);
Node fBlock = new Node(Token.FINALLY, finallyBlock);
fBlock.putProp(Node.LOCAL_BLOCK_PROP, handlerBlock);
pn.addChildToBack(fBlock);
pn.addChildToBack(finallyEnd);
}
handlerBlock.addChildToBack(pn);
return handlerBlock;
}
use of org.mozilla.javascript.ast.Jump in project HL4A by HL4A.
the class IRFactory method createIf.
private Node createIf(Node cond, Node ifTrue, Node ifFalse, int lineno) {
int condStatus = isAlwaysDefinedBoolean(cond);
if (condStatus == ALWAYS_TRUE_BOOLEAN) {
return ifTrue;
} else if (condStatus == ALWAYS_FALSE_BOOLEAN) {
if (ifFalse != null) {
return ifFalse;
}
// Replace if (false) xxx by empty block
return new Node(Token.BLOCK, lineno);
}
Node result = new Node(Token.BLOCK, lineno);
Node ifNotTarget = Node.newTarget();
Jump IFNE = new Jump(Token.IFNE, cond);
IFNE.target = ifNotTarget;
result.addChildToBack(IFNE);
result.addChildrenToBack(ifTrue);
if (ifFalse != null) {
Node endTarget = Node.newTarget();
result.addChildToBack(makeJump(Token.GOTO, endTarget));
result.addChildToBack(ifNotTarget);
result.addChildrenToBack(ifFalse);
result.addChildToBack(endTarget);
} else {
result.addChildToBack(ifNotTarget);
}
return result;
}
use of org.mozilla.javascript.ast.Jump in project HL4A by HL4A.
the class IRFactory method makeJump.
private Jump makeJump(int type, Node target) {
Jump n = new Jump(type);
n.target = target;
return n;
}
Aggregations