Search in sources :

Example 6 with Completion

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));
}
Also used : Completion(com.github.anba.es6draft.compiler.StatementGenerator.Completion) TryCatchLabel(com.github.anba.es6draft.compiler.assembler.TryCatchLabel) Jump(com.github.anba.es6draft.compiler.assembler.Jump) TempLabel(com.github.anba.es6draft.compiler.Labels.TempLabel)

Example 7 with Completion

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());
}
Also used : Completion(com.github.anba.es6draft.compiler.StatementGenerator.Completion) SwitchClause(com.github.anba.es6draft.ast.SwitchClause) Jump(com.github.anba.es6draft.compiler.assembler.Jump)

Example 8 with Completion

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());
}
Also used : Completion(com.github.anba.es6draft.compiler.StatementGenerator.Completion) LexicalEnvironment(com.github.anba.es6draft.runtime.LexicalEnvironment) BlockScope(com.github.anba.es6draft.ast.scope.BlockScope) BreakLabel(com.github.anba.es6draft.compiler.Labels.BreakLabel) Jump(com.github.anba.es6draft.compiler.assembler.Jump)

Example 9 with Completion

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));
}
Also used : Completion(com.github.anba.es6draft.compiler.StatementGenerator.Completion) SimpleImmutableEntry(java.util.AbstractMap.SimpleImmutableEntry) LabelState(com.github.anba.es6draft.compiler.CodeVisitor.LabelState) MethodCode(com.github.anba.es6draft.compiler.assembler.Code.MethodCode) GeneratorState(com.github.anba.es6draft.compiler.CodeVisitor.GeneratorState)

Example 10 with Completion

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();
}
Also used : Completion(com.github.anba.es6draft.compiler.StatementGenerator.Completion) MethodCode(com.github.anba.es6draft.compiler.assembler.Code.MethodCode)

Aggregations

Completion (com.github.anba.es6draft.compiler.StatementGenerator.Completion)11 MethodCode (com.github.anba.es6draft.compiler.assembler.Code.MethodCode)6 Jump (com.github.anba.es6draft.compiler.assembler.Jump)5 GeneratorState (com.github.anba.es6draft.compiler.CodeVisitor.GeneratorState)3 LegacyComprehensionFor (com.github.anba.es6draft.ast.LegacyComprehensionFor)2 BlockScope (com.github.anba.es6draft.ast.scope.BlockScope)2 LabelState (com.github.anba.es6draft.compiler.CodeVisitor.LabelState)2 MutableValue (com.github.anba.es6draft.compiler.assembler.MutableValue)2 LexicalEnvironment (com.github.anba.es6draft.runtime.LexicalEnvironment)2 ScriptIterator (com.github.anba.es6draft.runtime.internal.ScriptIterator)2 SimpleImmutableEntry (java.util.AbstractMap.SimpleImmutableEntry)2 ArrayList (java.util.ArrayList)2 List (java.util.List)2 ComprehensionFor (com.github.anba.es6draft.ast.ComprehensionFor)1 IterationKind (com.github.anba.es6draft.ast.LegacyComprehensionFor.IterationKind)1 SwitchClause (com.github.anba.es6draft.ast.SwitchClause)1 Name (com.github.anba.es6draft.ast.scope.Name)1 BreakLabel (com.github.anba.es6draft.compiler.Labels.BreakLabel)1 TempLabel (com.github.anba.es6draft.compiler.Labels.TempLabel)1 MethodName (com.github.anba.es6draft.compiler.assembler.MethodName)1