Search in sources :

Example 31 with IType

use of dyvilx.tools.compiler.ast.type.IType in project Dyvil by Dyvil.

the class MatchExpr method generateSwitch.

private void generateSwitch(MethodWriter writer, Object frameType) throws BytecodeException {
    MatchCase defaultCase = null;
    Label defaultLabel = null;
    int cases = 0;
    // the minimum int
    int low = Integer.MAX_VALUE;
    // the maximum int
    int high = Integer.MIN_VALUE;
    // Do we need to store the value in a variable (for string equality checks later)
    boolean switchVar = false;
    // generated.
    for (int i = 0; i < this.caseCount; i++) {
        MatchCase matchCase = this.cases[i];
        Pattern pattern = matchCase.pattern;
        if (switchVar || pattern.switchCheck()) {
            switchVar = true;
        }
        if (pattern.isExhaustive()) {
            defaultCase = matchCase;
            defaultLabel = new Label();
            continue;
        }
        int min = pattern.minValue();
        if (min < low) {
            low = min;
        }
        int max = pattern.maxValue();
        if (max > high) {
            high = max;
        }
        cases += pattern.subPatterns();
    }
    // Check if a match error should be generated - Non-exhaustive pattern
    // and no default label
    final Label endLabel = new Label();
    Label matchErrorLabel = null;
    if (!this.exhaustive) {
        // Need a variable for MatchError
        switchVar = true;
        matchErrorLabel = new Label();
        if (defaultLabel == null) {
            defaultLabel = matchErrorLabel;
        }
    } else if (defaultLabel == null) {
        // Exhaustive pattern - default label is end label
        defaultLabel = endLabel;
    }
    final boolean expr = frameType != null;
    // Write the value
    final IType matchedType = this.matchedValue.getType();
    final int localCount = writer.localCount();
    final int varIndex;
    if (switchVar) {
        varIndex = this.matchedValue.writeStoreLoad(writer, null);
    } else {
        varIndex = -1;
        this.matchedValue.writeExpression(writer, null);
    }
    if (Types.isSuperClass(Types.ENUM, matchedType)) {
        // x.name().hashCode()
        writer.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Enum", "name", "()Ljava/lang/String;", false);
        writer.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "hashCode", "()I", false);
    } else if (Types.isSuperClass(Types.STRING, matchedType)) {
        // x.hashCode()
        writer.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "hashCode", "()I", false);
    } else if (matchedType.getAnnotation(Types.SWITCHOPTIMIZED_CLASS) != null) {
        // x.getClass().getName().hashCode()
        writer.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;", false);
        writer.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getName", "()Ljava/lang/String;", false);
        writer.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "hashCode", "()I", false);
    }
    final int localCountInner = writer.localCount();
    final KeyCache keyCache = new KeyCache(cases);
    // Third run: fill the Key Cache
    for (int i = 0; i < this.caseCount; i++) {
        final MatchCase matchCase = this.cases[i];
        final Pattern pattern = matchCase.pattern;
        final int subPatterns = pattern.subPatterns();
        for (int j = 0; j < subPatterns; j++) {
            final Pattern subPattern = pattern.subPattern(j);
            if (subPattern.isExhaustive()) {
                continue;
            }
            final int switchValue = subPattern.switchValue();
            keyCache.add(switchValue, matchCase, subPattern);
        }
    }
    final Collection<KeyCache.Entry> entries = keyCache.uniqueEntries();
    // Generate switch target labels
    for (KeyCache.Entry topEntry : entries) {
        for (KeyCache.Entry entry = topEntry; entry != null; entry = entry.next) {
            entry.switchLabel = new Label();
        }
    }
    // Choose and generate the appropriate instruction
    if (useTableSwitch(low, high, cases)) {
        this.writeTableSwitch(writer, entries, defaultLabel, low, high);
    } else {
        this.writeLookupSwitch(writer, entries, defaultLabel, cases);
    }
    // Fourth run: generate the target labels
    for (KeyCache.Entry topEntry : entries) {
        KeyCache.Entry entry = topEntry;
        final int key = entry.key;
        do {
            final KeyCache.Entry next = entry.next;
            final MatchCase matchCase = entry.matchCase;
            final Pattern pattern = entry.pattern;
            Label elseLabel;
            if (next != null && next.key == key) {
                elseLabel = next.switchLabel;
                if (elseLabel == null) {
                    elseLabel = next.switchLabel = new Label();
                }
            } else {
                elseLabel = defaultLabel;
            }
            writer.visitTargetLabel(entry.switchLabel);
            if (pattern.switchCheck()) {
                pattern.writeJumpOnMismatch(writer, varIndex, elseLabel);
            }
            if (matchCase.condition != null) {
                matchCase.condition.writeInvJump(writer, elseLabel);
            }
            this.writeAction(writer, expr, frameType, matchCase.action);
            writer.resetLocals(localCountInner);
            if (!writer.hasReturn()) {
                writer.visitJumpInsn(Opcodes.GOTO, endLabel);
            }
            entry = next;
        } while (entry != null && entry.key == key);
    }
    // Default Case
    if (defaultCase != null) {
        writer.visitTargetLabel(defaultLabel);
        if (defaultCase.pattern.switchCheck()) {
            defaultCase.pattern.writeJumpOnMismatch(writer, varIndex, matchErrorLabel);
        }
        if (defaultCase.condition != null) {
            defaultCase.condition.writeInvJump(writer, matchErrorLabel);
        }
        this.writeAction(writer, expr, frameType, defaultCase.action);
        writer.resetLocals(localCountInner);
        if (!writer.hasReturn()) {
            writer.visitJumpInsn(Opcodes.GOTO, endLabel);
        }
    }
    // Generate Match Error
    if (matchErrorLabel != null) {
        writer.visitLabel(matchErrorLabel);
        this.writeMatchError(writer, varIndex, matchedType);
    }
    writer.visitLabel(endLabel);
    writer.resetLocals(localCount);
}
Also used : Pattern(dyvilx.tools.compiler.ast.pattern.Pattern) Label(dyvilx.tools.asm.Label) IType(dyvilx.tools.compiler.ast.type.IType)

Example 32 with IType

use of dyvilx.tools.compiler.ast.type.IType in project Dyvil by Dyvil.

the class EnumConstant method check.

@Override
public void check(MarkerList markers, IContext context) {
    final IClass enclosingClass = this.getEnclosingClass();
    final IType classType = enclosingClass.getClassType();
    if (!enclosingClass.hasModifier(Modifiers.ENUM_CLASS)) {
        final Marker marker = Markers.semanticError(this.position, "field.enum.class", this.name);
        marker.addInfo(Markers.getSemantic("method.enclosing_class", classType));
        markers.add(marker);
    }
    super.check(markers, context);
}
Also used : IClass(dyvilx.tools.compiler.ast.classes.IClass) Marker(dyvilx.tools.parsing.marker.Marker) IType(dyvilx.tools.compiler.ast.type.IType)

Example 33 with IType

use of dyvilx.tools.compiler.ast.type.IType in project Dyvil by Dyvil.

the class IDataMember method toString.

static void toString(String prefix, StringBuilder buffer, IMember field, String key) {
    final IType type = field.getType();
    appendKeyword(buffer, field);
    buffer.append(' ').append(field.getName());
    if (type != null && type != Types.UNKNOWN) {
        Formatting.appendSeparator(buffer, key, ':');
        type.toString(prefix, buffer);
    }
}
Also used : IType(dyvilx.tools.compiler.ast.type.IType)

Example 34 with IType

use of dyvilx.tools.compiler.ast.type.IType in project Dyvil by Dyvil.

the class IVariable method writeLocal.

default void writeLocal(MethodWriter writer, Label start, Label end) {
    final IType internalType = this.getInternalType();
    final String signature = internalType.needsSignature() ? internalType.getSignature() : null;
    writer.visitLocalVariable(this.getInternalName(), this.getDescriptor(), signature, start, end, this.getLocalIndex());
}
Also used : IType(dyvilx.tools.compiler.ast.type.IType)

Example 35 with IType

use of dyvilx.tools.compiler.ast.type.IType in project Dyvil by Dyvil.

the class ThisExpr method resolveTypes.

@Override
public void resolveTypes(MarkerList markers, IContext context) {
    if (this.type != Types.UNKNOWN) {
        this.type = this.type.resolveType(markers, context);
        // Replace e.g. this<List> with this<List<T>> in class List<type T>
        final IClass iclass = this.type.getTheClass();
        if (iclass != null) {
            this.type = iclass.getThisType();
        }
        return;
    }
    final IType thisType = context.getThisType();
    if (thisType != null) {
        this.type = thisType;
    } else {
        markers.add(Markers.semanticError(this.position, "this.access.unresolved"));
    }
}
Also used : IClass(dyvilx.tools.compiler.ast.classes.IClass) IType(dyvilx.tools.compiler.ast.type.IType)

Aggregations

IType (dyvilx.tools.compiler.ast.type.IType)159 IClass (dyvilx.tools.compiler.ast.classes.IClass)26 Marker (dyvilx.tools.parsing.marker.Marker)23 IValue (dyvilx.tools.compiler.ast.expression.IValue)21 TypeParameterList (dyvilx.tools.compiler.ast.generic.TypeParameterList)13 ParameterList (dyvilx.tools.compiler.ast.parameter.ParameterList)11 IParameter (dyvilx.tools.compiler.ast.parameter.IParameter)10 SourcePosition (dyvil.source.position.SourcePosition)9 Annotation (dyvilx.tools.compiler.ast.attribute.annotation.Annotation)9 ITypeParameter (dyvilx.tools.compiler.ast.generic.ITypeParameter)9 ArgumentList (dyvilx.tools.compiler.ast.parameter.ArgumentList)9 TypeList (dyvilx.tools.compiler.ast.type.TypeList)7 AttributeList (dyvilx.tools.compiler.ast.attribute.AttributeList)6 FieldAccess (dyvilx.tools.compiler.ast.expression.access.FieldAccess)6 IVariable (dyvilx.tools.compiler.ast.field.IVariable)6 ArrayType (dyvilx.tools.compiler.ast.type.compound.ArrayType)6 MethodWriter (dyvilx.tools.compiler.backend.MethodWriter)6 CodeMethod (dyvilx.tools.compiler.ast.method.CodeMethod)5 CodeParameter (dyvilx.tools.compiler.ast.parameter.CodeParameter)5 Name (dyvil.lang.Name)4