Улучшить алгоритм разрешения переопределения / абстрактного метода

Следующие фрагменты кода определяют, как компилятор для моего пользовательского языка программирования JVM разрешает отсутствующие абстрактные методы и связывает методы с их методами супертипа. Модель наследования похожа на Java 8, вы можете иметь как абстрактные, так и конкретные (по умолчанию) методы в интерфейсах, а также абстрактные классы и конкретные методы только в неабстрактных классах. Множественное наследование разрешено только для интерфейсов:

CodeClass.java:

public class CodeClass extends AbstractClass
{
    // ...
    public void checkTypes(MarkerList markers, IContext context)
    {
        // ...
        if (this.superType != null)
        {
            this.superType.getTheClass().checkMethods(markers, this, this.superType);
        }
        for (int i = 0; i < this.interfaceCount; i++)
        {
            IType type = this.interfaces[i];
            type.getTheClass().checkMethods(markers, this, type);
        }
    }
    // ...
}

AbstractClass.java:

public class AbstractClass
{
    protected ClassBody body;

    // ...        

    public boolean checkImplements(MarkerList markers, IClass iclass, IMethod candidate, ITypeContext typeContext)
    {
        if (candidate.getTheClass() == this)
        {
            return !candidate.hasModifier(Modifiers.ABSTRACT);
        }

        if (this.body != null && this.body.checkImplements(markers, iclass, candidate, typeContext))
        {
            return true;
        }

        if (this.superType != null)
        {
            if (this.superType.getTheClass().checkImplements(markers, iclass, candidate, this.superType.getConcreteType(typeContext)))
            {
                return true;
            }
        }

        for (int i = 0; i < this.interfaceCount; i++)
        {
            IType type = this.interfaces[i];
            if (type.getTheClass().checkImplements(markers, iclass, candidate, type.getConcreteType(typeContext)))
            {
                return true;
            }
        }

        return false;
    }

    public void checkMethods(MarkerList markers, IClass iclass, ITypeContext typeContext)
    {
        if (this.body != null)
        {
            this.body.checkMethods(markers, iclass, typeContext);
        }

        if (this.superType != null)
        {
            this.superType.getTheClass().checkMethods(markers, iclass, this.superType.getConcreteType(typeContext));
        }
        for (int i = 0; i < this.interfaceCount; i++)
        {
            IType type = this.interfaces[i];
            type.getTheClass().checkMethods(markers, iclass, type.getConcreteType(typeContext));
        }
    }
    // ...
}

ClassBody.java:

public class ClassBody
{
    // ...

    public boolean checkImplements(MarkerList markers, IClass iclass, IMethod candidate, ITypeContext typeContext)
    {
        for (int i = 0; i < this.methodCount; i++)
        {
            if (this.methods[i].checkOverride(markers, iclass, candidate, typeContext))
            {
                return true;
            }
        }
        return false;
    }

    public void checkMethods(MarkerList markers, IClass iclass, ITypeContext typeContext)
    {
        for (int i = 0; i < this.methodCount; i++)
        {
            IMethod candidate = this.methods[i];
            if (iclass.checkImplements(markers, iclass, candidate, typeContext))
            {
                continue;
            }

            if (candidate.hasModifier(Modifiers.ABSTRACT) && !iclass.hasModifier(Modifiers.ABSTRACT))
            {
                markers.add(iclass.getPosition(), "class.method.abstract", iclass.getName(), candidate.getName(), this.theClass.getName());
            }
        }
    }

    // ...
}

method.checkOverride просто проверяет, совпадают ли подпись кандидата и получателя, и iclass Параметр и контейнерный класс метода одного типа, кандидат добавляется в список переопределенных методов.

Этот код хорош и симпатичен, а также работает так, как я и предполагал, но я боюсь, что он взорвется для глубокой иерархии классов с большим количеством методов (например, каркас коллекции), потому что весь процесс является сильно рекурсивным операция, которая требует много-много проверок типов и многократного перебора массивов методов. Существует ли менее сложное и более производительное решение для больших деревьев классов и как работают другие компиляторы (например, javac или же scalac) решить эту проблему?

0 ответов

Другие вопросы по тегам