use of com.github.anba.es6draft.compiler.StatementGenerator.Completion in project es6draft by anba.
the class AbstractIterationGenerator method generate.
/**
* Emit code for the wrapped iteration.
*
* @param node
* the ast node
* @param iterator
* the iterator variable
* @param target
* the target label
* @param mv
* the code visitor
* @return the completion value
*/
public final Completion generate(NODE node, Variable<ITERATOR> iterator, Jump target, CodeVisitor mv) {
TryCatchLabel startIteration = new TryCatchLabel(), endIteration = new TryCatchLabel();
TryCatchLabel handlerCatch = new TryCatchLabel();
TryCatchLabel handlerCatchStackOverflow = null;
if (codegen.isEnabled(Compiler.Option.IterationCatchStackOverflow)) {
handlerCatchStackOverflow = new TryCatchLabel();
}
boolean hasTarget = target != null;
if (!hasTarget) {
target = new Jump();
}
mv.enterVariableScope();
MutableValue<Object> completion = enterIteration(node, mv);
// Emit loop body
mv.mark(startIteration);
Completion loopBodyResult = iterationBody(node, iterator, mv);
if (!loopBodyResult.isAbrupt()) {
mv.goTo(target);
}
mv.mark(endIteration);
// Restore temporary abrupt targets
List<TempLabel> tempLabels = exitIteration(node, mv);
// Emit throw handler
Completion throwResult = emitThrowHandler(node, iterator, handlerCatch, handlerCatchStackOverflow, mv);
// Emit return handler
Completion returnResult = emitReturnHandler(node, iterator, completion, tempLabels, mv);
mv.exitVariableScope();
mv.tryCatch(startIteration, endIteration, handlerCatch, Types.ScriptException);
if (handlerCatchStackOverflow != null) {
mv.tryCatch(startIteration, endIteration, handlerCatchStackOverflow, Types.Error);
}
if (!hasTarget) {
mv.mark(target);
epilogue(node, iterator, mv);
}
if (tempLabels.isEmpty()) {
// No Return handler installed
return throwResult.select(loopBodyResult);
}
return returnResult.select(throwResult.select(loopBodyResult));
}
use of com.github.anba.es6draft.compiler.StatementGenerator.Completion in project es6draft by anba.
the class SwitchStatementGenerator method CaseBlockEvaluation.
/**
* 13.12.9 Runtime Semantics: CaseBlockEvaluation
*
* @param node
* the switch statement
* @param type
* the switch statement type
* @param lblExit
* the exit label
* @param switchValue
* the variable which holds the switch value
* @param mv
* the code visitor
* @return the completion value
*/
private Completion CaseBlockEvaluation(SwitchStatement node, SwitchType type, Jump lblExit, Variable<?> switchValue, CodeVisitor mv) {
List<SwitchClause> clauses = node.getClauses();
Jump lblDefault = null;
Jump[] labels = new Jump[clauses.size()];
for (int i = 0, size = clauses.size(); i < size; ++i) {
labels[i] = new Jump();
if (clauses.get(i).isDefaultClause()) {
assert lblDefault == null;
lblDefault = labels[i];
}
}
if (type == SwitchType.Int) {
emitIntSwitch(clauses, labels, lblDefault, lblExit, switchValue, mv);
} else if (type == SwitchType.Char) {
emitCharSwitch(clauses, labels, lblDefault, lblExit, switchValue, mv);
} else if (type == SwitchType.String) {
emitStringSwitch(clauses, labels, lblDefault, lblExit, switchValue, mv);
} else if (type == SwitchType.Generic) {
emitGenericSwitch(clauses, labels, lblDefault, lblExit, switchValue, mv);
} else {
assert type == SwitchType.Default;
assert switchValue == null;
// Directly jump to default clause; since switch clauses before default clause are not
// emitted, jump instruction can be elided as well, so we directly fall into the default
// clause.
}
Completion result = Completion.Normal, lastResult = Completion.Normal;
if (type == SwitchType.Default) {
Iterator<SwitchClause> iter = clauses.iterator();
// skip leading clauses until default clause found
while (iter.hasNext()) {
SwitchClause switchClause = iter.next();
if (switchClause.isDefaultClause()) {
lastResult = switchClause.accept(this, mv);
break;
}
}
// handle clauses following default clause until abrupt completion
while (iter.hasNext() && !lastResult.isAbrupt()) {
lastResult = iter.next().accept(this, mv);
}
result = lastResult;
} else {
int index = 0;
for (SwitchClause switchClause : clauses) {
Jump caseLabel = labels[index++];
if (caseLabel != null) {
mv.mark(caseLabel);
} else if (lastResult.isAbrupt()) {
// Ignore unreachable targets
continue;
}
Completion innerResult = switchClause.accept(this, mv);
if (innerResult.isAbrupt()) {
// not fall-thru
result = result.isAbrupt() ? result.select(innerResult) : innerResult;
}
lastResult = innerResult;
}
}
return result.normal(lblDefault == null || !lastResult.isAbrupt());
}
use of com.github.anba.es6draft.compiler.StatementGenerator.Completion in project es6draft by anba.
the class SwitchStatementGenerator method visit.
/**
* 13.12.11 Runtime Semantics: Evaluation
*/
@Override
public Completion visit(SwitchStatement node, CodeVisitor mv) {
// stack -> switchValue
ValType switchValueType = expression(node.getExpression(), mv);
SwitchType type = SwitchType.of(node);
boolean defaultOrReturn = false;
if (type == SwitchType.Int) {
if (!switchValueType.isNumeric() && switchValueType != ValType.Any) {
defaultOrReturn = true;
}
} else if (type == SwitchType.Char) {
if (switchValueType != ValType.String && switchValueType != ValType.Any) {
defaultOrReturn = true;
}
} else if (type == SwitchType.String) {
if (switchValueType != ValType.String && switchValueType != ValType.Any) {
defaultOrReturn = true;
}
} else if (type == SwitchType.Generic) {
mv.toBoxed(switchValueType);
switchValueType = ValType.Any;
} else {
assert type == SwitchType.Default;
defaultOrReturn = true;
}
final boolean defaultClausePresent = hasDefaultClause(node);
if (defaultOrReturn) {
// never true -> emit default switch or return
mv.pop(switchValueType);
if (defaultClausePresent) {
type = SwitchType.Default;
} else {
return Completion.Normal;
}
}
mv.enterVariableScope();
Variable<LexicalEnvironment<?>> savedEnv = saveEnvironment(node, mv);
Variable<?> switchValue = null;
if (type != SwitchType.Default) {
switchValue = mv.newVariable("switchValue", switchValueType.toClass());
mv.store(switchValue);
}
BlockScope scope = node.getScope();
if (scope.isPresent()) {
newDeclarativeEnvironment(scope, mv);
codegen.blockInit(node, mv);
pushLexicalEnvironment(mv);
}
Jump lblExit = new Jump();
BreakLabel lblBreak = new BreakLabel();
mv.enterScope(node);
mv.enterBreakable(node, lblBreak);
Completion result = CaseBlockEvaluation(node, type, lblExit, switchValue, mv);
mv.exitBreakable(node);
mv.exitScope();
if (!defaultClausePresent) {
mv.mark(lblExit);
}
if (scope.isPresent() && !result.isAbrupt()) {
popLexicalEnvironment(mv);
}
if (lblBreak.isTarget()) {
mv.mark(lblBreak);
restoreEnvironment(savedEnv, mv);
}
mv.exitVariableScope();
return result.normal(lblBreak.isTarget());
}
use of com.github.anba.es6draft.compiler.StatementGenerator.Completion in project es6draft by anba.
the class CodeGenerator method compile.
Entry<MethodName, LabelState> compile(StatementListMethod node, CodeVisitor mv) {
if (!isCompiled(node)) {
MethodCode method = newMethod(mv.getTopLevelNode(), node);
StatementListMethodCodeVisitor body = new StatementListMethodCodeVisitor(node, method, mv);
body.lineInfo(node);
// force line-number entry
body.nop();
body.begin();
GeneratorState generatorState = null;
if (node.hasResumePoint()) {
generatorState = body.generatorPrologue();
}
body.labelPrologue();
Completion result = statements(node.getStatements(), body);
if (!result.isAbrupt()) {
// fall-thru, return `0`.
body.iconst(0);
body._return();
}
LabelState labelState = body.labelEpilogue(result);
if (generatorState != null) {
body.generatorEpilogue(generatorState);
}
body.end();
statementCompletions.put(node, labelState);
}
return new SimpleImmutableEntry<>(methodDesc(node), statementCompletions.get(node));
}
use of com.github.anba.es6draft.compiler.StatementGenerator.Completion in project es6draft by anba.
the class CodeGenerator method moduleBody.
private void moduleBody(Module node) {
MethodCode method = newMethod(node, ModuleName.Code);
ModuleCodeVisitor body = new ModuleCodeVisitor(method, node);
body.lineInfo(node);
body.begin();
body.enterScope(node);
Completion result = statements(node.getStatements(), body);
body.exitScope();
if (!result.isAbrupt()) {
// Completion values are currently ignored for module code.
body.loadUndefined();
body._return();
}
body.end();
}
Aggregations