use of com.github.anba.es6draft.compiler.assembler.Jump in project es6draft by anba.
the class StatementGenerator method visit.
/**
* 13.7.3 The while Statement
* <p>
* 13.1.8 Runtime Semantics: Evaluation<br>
* 13.1.7 Runtime Semantics: LabelledEvaluation<br>
* 13.7.3.6 Runtime Semantics: LabelledEvaluation
*/
@Override
public Completion visit(WhileStatement node, CodeVisitor mv) {
assert mv.getStackSize() == 0;
Jump lblNext = new Jump(), lblTest = new Jump();
ContinueLabel lblContinue = new ContinueLabel();
BreakLabel lblBreak = new BreakLabel();
Bool btest = Bool.evaluate(node.getTest());
mv.enterVariableScope();
Variable<LexicalEnvironment<?>> savedEnv = saveEnvironment(node, mv);
/* step 1 */
if (node.hasCompletionValue()) {
mv.storeUndefinedAsCompletionValue();
}
/* step 2 (repeat loop) */
if (btest != Bool.True) {
mv.nonDestructiveGoTo(lblTest);
}
mv.mark(lblNext);
/* steps 2.e-g */
Completion result;
{
mv.enterIteration(node, lblBreak, lblContinue);
result = node.getStatement().accept(this, mv);
mv.exitIteration(node);
}
/* step 2.f (abrupt completion - continue) */
if (lblContinue.isTarget()) {
mv.mark(lblContinue);
restoreEnvironment(savedEnv, mv);
}
/* steps 2.a-d */
if (btest != Bool.True) {
mv.mark(lblTest);
ValType type = expression(node.getTest(), mv);
ToBoolean(type, mv);
mv.ifne(lblNext);
} else if (!result.isAbrupt() || lblContinue.isTarget()) {
mv.goTo(lblNext);
}
/* step 2.f (abrupt completion - break) */
if (lblBreak.isTarget()) {
mv.mark(lblBreak);
restoreEnvironment(savedEnv, mv);
}
mv.exitVariableScope();
/* steps 2.d, 2.f */
if (btest == Bool.True) {
if (!result.isAbrupt() && !lblBreak.isTarget()) {
// infinite loop
return Completion.Abrupt;
}
return result.normal(lblBreak.isTarget());
}
return Completion.Normal;
}
use of com.github.anba.es6draft.compiler.assembler.Jump in project es6draft by anba.
the class StatementGenerator method ForInOfHeadEvaluation.
/**
* 13.7.5.12 Runtime Semantics: ForIn/OfHeadEvaluation (TDZnames, expr, iterationKind, labelSet)
* <p>
* stack: [] {@literal ->} [Iterator]
*
* @param <FORSTATEMENT>
* the for-statement node type
* @param node
* the for-statement node
* @param iterationKind
* the for-statement's iteration kind
* @param lblFail
* the target instruction if the expression node does not produce an object type
* @param mv
* the code visitor
* @return the value type of the expression
*/
private <FORSTATEMENT extends IterationStatement & ForIterationNode> ValType ForInOfHeadEvaluation(FORSTATEMENT node, IterationKind iterationKind, Jump lblFail, CodeVisitor mv) {
/* steps 1-2 */
BlockScope scope = node.getScope();
Node lhs = node.getHead();
List<Name> tdzNames = null;
if (lhs instanceof LexicalDeclaration) {
tdzNames = BoundNames(forDeclarationBinding((LexicalDeclaration) lhs));
assert scope.isPresent() == !tdzNames.isEmpty();
if (scope.isPresent()) {
// stack: [] -> [TDZ]
newDeclarativeEnvironment(scope, mv);
mv.enterVariableScope();
Variable<DeclarativeEnvironmentRecord> envRec = mv.newVariable("envRec", DeclarativeEnvironmentRecord.class);
getEnvRec(envRec, mv);
// stack: [TDZ] -> [TDZ]
for (Name name : tdzNames) {
BindingOp<DeclarativeEnvironmentRecord> op = BindingOp.of(envRec, name);
op.createMutableBinding(envRec, name, false, mv);
}
mv.exitVariableScope();
// stack: [TDZ] -> []
pushLexicalEnvironment(mv);
}
mv.enterScope(node);
}
/* steps 3, 5-6 */
Expression expr = node.getExpression();
ValType type = expressionBoxed(expr, mv);
/* step 4 */
if (tdzNames != null) {
mv.exitScope();
if (scope.isPresent()) {
popLexicalEnvironment(mv);
}
}
/* steps 7-8 */
if (iterationKind == IterationKind.Enumerate || iterationKind == IterationKind.EnumerateValues) {
/* step 7.a */
if (type != ValType.Object) {
Jump loopstart = new Jump();
mv.dup();
isUndefinedOrNull(mv);
mv.ifeq(loopstart);
mv.pop();
mv.goTo(lblFail);
mv.mark(loopstart);
}
/* steps 7.b-c */
if (codegen.isEnabled(CompatibilityOption.LegacyGenerator)) {
// legacy generator mode, both, for-in and for-each, perform Iterate on generators
Jump l0 = new Jump(), l1 = new Jump();
mv.dup();
mv.instanceOf(Types.GeneratorObject);
mv.ifeq(l0);
mv.dup();
mv.checkcast(Types.GeneratorObject);
mv.invoke(Methods.GeneratorObject_isLegacyGenerator);
mv.ifeq(l0);
mv.loadExecutionContext();
mv.lineInfo(expr);
mv.invoke(Methods.ScriptRuntime_iterate);
mv.goTo(l1);
mv.mark(l0);
mv.loadExecutionContext();
if (iterationKind == IterationKind.Enumerate) {
mv.lineInfo(expr);
mv.invoke(Methods.ScriptRuntime_enumerate);
} else {
mv.lineInfo(expr);
mv.invoke(Methods.ScriptRuntime_enumerateValues);
}
mv.mark(l1);
} else if (iterationKind == IterationKind.Enumerate) {
mv.loadExecutionContext();
mv.lineInfo(expr);
mv.invoke(Methods.ScriptRuntime_enumerate);
} else {
mv.loadExecutionContext();
mv.lineInfo(expr);
mv.invoke(Methods.ScriptRuntime_enumerateValues);
}
} else if (iterationKind == IterationKind.AsyncIterate) {
mv.loadExecutionContext();
mv.lineInfo(expr);
mv.invoke(Methods.ScriptRuntime_asyncIterate);
} else {
/* step 8 */
assert iterationKind == IterationKind.Iterate;
mv.loadExecutionContext();
mv.lineInfo(expr);
mv.invoke(Methods.ScriptRuntime_iterate);
}
return type;
}
use of com.github.anba.es6draft.compiler.assembler.Jump in project es6draft by anba.
the class StatementGenerator method visitForInOfLoop.
/**
* 13.7.5.11 Runtime Semantics: LabelledEvaluation
*
* @param <FORSTATEMENT>
* the for-statement node type
* @param node
* the for-statement node
* @param expr
* the expression node
* @param lhs
* the left-hand side node
* @param stmt
* the statement node
* @param iterationKind
* the for-statement's iteration kind
* @param mv
* the code visitor
* @return the completion value
*/
private <FORSTATEMENT extends IterationStatement & ForIterationNode> Completion visitForInOfLoop(FORSTATEMENT node, IterationKind iterationKind, CodeVisitor mv) {
assert mv.getStackSize() == 0;
Jump lblFail = new Jump();
/* steps 1-2 */
ValType type = ForInOfHeadEvaluation(node, iterationKind, lblFail, mv);
/* step 3 */
Completion result;
if (iterationKind != IterationKind.AsyncIterate) {
result = ForInOfBodyEvaluation(node, mv);
} else {
result = AsyncForInOfBodyEvaluation(node, mv);
}
if (type != ValType.Object) {
mv.mark(lblFail);
}
return result;
}
use of com.github.anba.es6draft.compiler.assembler.Jump in project es6draft by anba.
the class StatementGenerator method ForInOfBodyEvaluation.
/**
* 13.7.5.13 Runtime Semantics: ForIn/OfBodyEvaluation (lhs, stmt, iterator, lhsKind, labelSet)
* <p>
* stack: [Iterator] {@literal ->} []
*
* @param <FORSTATEMENT>
* the for-statement node type
* @param node
* the for-statement node
* @param mv
* the code visitor
* @return the completion value
*/
private <FORSTATEMENT extends IterationStatement & ForIterationNode> Completion ForInOfBodyEvaluation(FORSTATEMENT node, CodeVisitor mv) {
assert mv.getStackSize() == 1;
ContinueLabel lblContinue = new ContinueLabel();
BreakLabel lblBreak = new BreakLabel();
Jump enter = new Jump(), test = new Jump();
mv.enterVariableScope();
Variable<ScriptIterator<?>> iterator = mv.newVariable("iter", ScriptIterator.class).uncheckedCast();
// stack: [Iterator] -> []
mv.store(iterator);
Variable<Object> nextValue = mv.newVariable("nextValue", Object.class);
Variable<LexicalEnvironment<?>> savedEnv = saveEnvironment(node, mv);
/* step 2 */
if (node.hasCompletionValue()) {
mv.storeUndefinedAsCompletionValue();
}
/* steps 3-4 (not applicable) */
/* step 5 (repeat loop) */
mv.nonDestructiveGoTo(test);
/* steps 5.d-e */
mv.mark(enter);
mv.load(iterator);
mv.lineInfo(node);
mv.invoke(Methods.Iterator_next);
mv.store(nextValue);
/* steps 5.f-l */
{
mv.enterIteration(node, lblBreak, lblContinue);
mv.enterWrapped();
new IterationGenerator<FORSTATEMENT>(codegen) {
@Override
protected Completion iterationBody(FORSTATEMENT node, Variable<ScriptIterator<?>> iterator, CodeVisitor mv) {
return ForInOfBodyEvaluationInner(node, nextValue, mv);
}
@Override
protected MutableValue<Object> enterIteration(FORSTATEMENT node, CodeVisitor mv) {
return mv.enterIterationBody(node);
}
@Override
protected List<TempLabel> exitIteration(FORSTATEMENT node, CodeVisitor mv) {
return mv.exitIterationBody(node);
}
}.generate(node, iterator, test, mv);
mv.exitWrapped();
mv.exitIteration(node);
}
/* steps 5.m-n */
if (lblContinue.isTarget()) {
mv.mark(lblContinue);
restoreEnvironment(savedEnv, mv);
}
/* steps 5.a-c */
mv.mark(test);
mv.load(iterator);
mv.lineInfo(node);
mv.invoke(Methods.Iterator_hasNext);
mv.ifne(enter);
/* steps 5.m-n */
if (lblBreak.isTarget()) {
mv.mark(lblBreak);
restoreEnvironment(savedEnv, mv);
}
mv.exitVariableScope();
return Completion.Normal;
}
use of com.github.anba.es6draft.compiler.assembler.Jump in project es6draft by anba.
the class StatementGenerator method ForBodyEvaluation.
/**
* 13.7.4.8 Runtime Semantics: ForBodyEvaluation(test, increment, stmt, perIterationBindings,
* labelSet)
*/
private Completion ForBodyEvaluation(ForStatement node, boolean perIterationsLets, CodeVisitor mv) {
assert mv.getStackSize() == 0;
mv.enterVariableScope();
/* step 1 */
if (node.hasCompletionValue()) {
mv.storeUndefinedAsCompletionValue();
}
/* steps 2-3 */
Variable<LexicalEnvironment<?>> savedEnv;
if (perIterationsLets) {
savedEnv = mv.newVariable("savedEnv", LexicalEnvironment.class).uncheckedCast();
CreatePerIterationEnvironment(savedEnv, mv);
} else {
savedEnv = saveEnvironment(node, mv);
}
Jump lblTest = new Jump(), lblStmt = new Jump();
ContinueLabel lblContinue = new ContinueLabel();
BreakLabel lblBreak = new BreakLabel();
Bool btest = node.getTest() != null ? Bool.evaluate(node.getTest()) : Bool.True;
/* steps 4.b-d */
Completion result;
if (btest != Bool.True) {
mv.nonDestructiveGoTo(lblTest);
}
mv.mark(lblStmt);
{
mv.enterIteration(node, lblBreak, lblContinue);
result = node.getStatement().accept(this, mv);
mv.exitIteration(node);
}
/* step 4.c (abrupt completion - continue) */
if (lblContinue.isTarget()) {
mv.mark(lblContinue);
restoreEnvironment(savedEnv, mv);
}
/* steps 4.e-f */
if (perIterationsLets && (!result.isAbrupt() || lblContinue.isTarget())) {
CreatePerIterationEnvironment(savedEnv, mv);
}
/* step 4.g */
if (node.getStep() != null && (!result.isAbrupt() || lblContinue.isTarget())) {
ValType type = expression(node.getStep().emptyCompletion(), mv);
mv.pop(type);
}
/* step 4.a */
if (btest != Bool.True) {
mv.mark(lblTest);
ValType type = expression(node.getTest(), mv);
ToBoolean(type, mv);
mv.ifne(lblStmt);
} else {
mv.goTo(lblStmt);
}
/* step 4.c (abrupt completion - break) */
if (lblBreak.isTarget()) {
mv.mark(lblBreak);
restoreEnvironment(savedEnv, mv);
}
mv.exitVariableScope();
if (btest == Bool.True) {
if (!result.isAbrupt() && !lblBreak.isTarget()) {
// infinite loop
return Completion.Abrupt;
}
return result.normal(lblBreak.isTarget());
}
return Completion.Normal;
}
Aggregations