Search in sources :

Example 1 with StringLiteral

use of com.github.anba.es6draft.ast.StringLiteral in project es6draft by anba.

the class SwitchStatementGenerator method emitStringSwitch.

/**
     * <h3>String-switch</h3>
     * 
     * <pre>
     * switch (v) {
     * case "key1": ...
     * case "key2": ...
     * }
     * 
     * var $v = v;
     * if (typeof $v == 'string') {
     *   lookupswitch(hashCode($v)) {
     *     hashCode("key1"): goto L1
     *     hashCode("key2"): goto L2
     *   }
     *   L1: if (equals($v, "key1")) ...
     *   L2: if (equals($v, "key2")) ...
     * }
     * </pre>
     * 
     * @param clauses
     *            the switch clauses
     * @param labels
     *            the labels for each switch clause
     * @param defaultClause
     *            the label for the default clause
     * @param lblExit
     *            the exit label
     * @param switchValue
     *            the variable which holds the switch value
     * @param mv
     *            the code visitor
     */
private void emitStringSwitch(List<SwitchClause> clauses, Jump[] labels, Jump defaultClause, Jump lblExit, Variable<?> switchValue, CodeVisitor mv) {
    Jump switchDefault = defaultClause != null ? defaultClause : lblExit;
    mv.enterVariableScope();
    Variable<String> switchValueString = mv.newVariable("switchValueString", String.class);
    if (switchValue.getType().equals(Types.CharSequence)) {
        mv.load(switchValue);
        mv.invoke(Methods.CharSequence_toString);
        mv.dup();
        mv.store(switchValueString);
        mv.invoke(Methods.String_hashCode);
    } else {
        assert switchValue.getType().equals(Types.Object);
        // test for string: type is java.lang.CharSequence
        mv.load(switchValue);
        mv.instanceOf(Types.CharSequence);
        mv.ifeq(switchDefault);
        mv.load(switchValue);
        mv.checkcast(Types.CharSequence);
        mv.invoke(Methods.CharSequence_toString);
        mv.dup();
        mv.store(switchValueString);
        mv.invoke(Methods.String_hashCode);
    }
    long[] entries = stringSwitchEntries(clauses, defaultClause != null);
    int distinctValues = distinctValues(entries);
    Jump[] switchLabels = new Jump[distinctValues];
    int[] switchKeys = new int[distinctValues];
    for (int i = 0, j = 0, lastValue = 0, length = entries.length; i < length; ++i) {
        int value = Value(entries[i]);
        if (i == 0 || value != lastValue) {
            switchLabels[j] = new Jump();
            switchKeys[j] = value;
            j += 1;
        }
        lastValue = value;
    }
    // emit lookupswitch
    mv.lookupswitch(switchDefault, switchKeys, switchLabels);
    // add String.equals() calls
    for (int i = 0, j = 0, lastValue = 0, length = entries.length; i < length; ++i) {
        int value = Value(entries[i]);
        int index = Index(entries[i]);
        if (i == 0 || value != lastValue) {
            if (i != 0) {
                mv.goTo(switchDefault);
            }
            mv.mark(switchLabels[j++]);
        }
        String string = ((StringLiteral) clauses.get(index).getExpression()).getValue();
        mv.load(switchValueString);
        mv.aconst(string);
        mv.invoke(Methods.String_equals);
        mv.ifne(labels[index]);
        lastValue = value;
    }
    mv.goTo(switchDefault);
    mv.exitVariableScope();
}
Also used : StringLiteral(com.github.anba.es6draft.ast.StringLiteral) Jump(com.github.anba.es6draft.compiler.assembler.Jump)

Aggregations

StringLiteral (com.github.anba.es6draft.ast.StringLiteral)1 Jump (com.github.anba.es6draft.compiler.assembler.Jump)1