Project.avt

Переключить прокрутку окна
Загрузить этот исходный код

/*
    Компилятор языка программирования
    Объектно-ориентированный продвинутый векторный транслятор

    Copyright © 2021, 2024 Малик Разработчик

    Это свободная программа: вы можете перераспространять ее и/или изменять
    ее на условиях Стандартной общественной лицензии GNU в том виде,
    в каком она была опубликована Фондом свободного программного обеспечения;
    либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.

    Эта программа распространяется в надежде, что она будет полезной,
    но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
    или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Стандартной
    общественной лицензии GNU.

    Вы должны были получить копию Стандартной общественной лицензии GNU
    вместе с этой программой. Если это не так, см.
    <https://www.gnu.org/licenses/>.
*/

package ru.malik.elaborarer.avtoo.compiler;

import avt.io.*;
import avt.lang.array.*;
import ru.malik.elaborarer.avtoo.lang.*;

public abstract class Project(Programme, AVTOOConstants)
{
    public static final String PROGRAMME_DESTINATION_PATH   = "dst";
    public static final String BINARY_SOURCE_PATH           = "bin";
    public static final String ASSEMBLER_SOURCE_PATH        = "src.asm";
    public static final String TEXT_SOURCE_MAIN_PATH        = "src.avt";
    public static final String TEXT_SOURCE_ALTERNATIVE_PATH = "src";
    public static final String PACKAGE_SOURCE_EXTENSION     = ".avtpack";
    public static final String BINARY_SOURCE_EXTENSION      = ".avtoo-recompilable";
    public static final String TYPE_SOURCE_EXTENSION        = ".avt";

    public static boolean isPackageSourceFileName(String fileName) { return fileName != null && fileName.regionMatches(fileName.length - 8, PACKAGE_SOURCE_EXTENSION, 0, 8, true); }

    public static boolean isBinarySourceFileName(String fileName) { return fileName != null && fileName.regionMatches(fileName.length - 19, BINARY_SOURCE_EXTENSION, 0, 19, true); }

    public static boolean isTypeSourceFileName(String fileName) { return fileName != null && fileName.regionMatches(fileName.length - 4, TYPE_SOURCE_EXTENSION, 0, 4, true); }

    private int fldMaxThreads;
    private final StringArray fldExcludes;

    protected (int pointerSize): super(pointerSize) {
        fldMaxThreads = Int.MAX_VALUE;
        fldExcludes = new ProjectNonNullStringArray();
    }

    public void compile() throws IOException, CompilerException {
        /* 1. Стадия загрузки данных. Поиск и чтение файлов исходного кода. */
        (new CompilerParallelWorker(maxThreads) { targets = libraries }).run(new ProjectSourcesLoader(this));
    }

    public final int maxThreads { read = fldMaxThreads, write = setMaxThreads }

    public final StringArray excludes { read = fldExcludes }

    protected abstract void prefetchSupertypesForPrimitiveArray(ArrayType array);

    protected abstract void prefetchSupertypesForObjectArray(ArrayType array);

    protected abstract void prefetchSupertypesForReferenceArray(ArrayType array);

    protected abstract void createMembersForPrimitiveArray(ArrayType array);

    protected abstract void createMembersForObjectArray(ArrayType array);

    protected abstract String getSourceType(Library library);

    protected void setMaxThreads(int newMaxThreads) { fldMaxThreads = newMaxThreads < 1 ? 1 : newMaxThreads; }
}

final class ProjectNonNullStringArray(StringArray, Cloneable, Measureable, ObjectArray)
{
    public () {  }

    public void append(String item) {
        if(item == null)
        {
            throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument"), new Object[] { "item" }));
        }
        super.append(item);
    }

    public boolean contains(String item) { return item != null && super.contains(item); }
}

final class ProjectSourcesLoader(Object, CompilerRunnable, AVTOOConstants)
{
    private final Project fldParentProject;

    public (Project parentProject) { fldParentProject = parentProject; }

    public void run(Object target) throws IOException {
        with(fldParentProject)
        {
            Library library = (Library) target;
            String type = getSourceType(library);
            if(type == null)
            {
                throw new NullPointerException(package.getResourceString("source.type.null"));
            }
            label0:
            {
                if(type.equals(TEXT_SOURCE)) with(library.fileSystem, library.directoryPath)
                {
                    findPackageSources(library);
                    if(isObjectExists(operator +(TEXT_SOURCE_MAIN_PATH)))
                    {
                        findTypeSources(library, TEXT_SOURCE_MAIN_PATH + "/");
                        break label0;
                    }
                    if(isObjectExists(operator +(TEXT_SOURCE_ALTERNATIVE_PATH)))
                    {
                        findTypeSources(library, TEXT_SOURCE_ALTERNATIVE_PATH + "/");
                    }
                    break label0;
                }
                if(type.equals(BINARY_SOURCE)) with(library.fileSystem, library.directoryPath)
                {
                    if(isObjectExists(operator +(BINARY_SOURCE_PATH)))
                    {
                        findBinarySources(library, BINARY_SOURCE_PATH + "/");
                    }
                    break label0;
                }
                throw new IOException(String.format(package.getResourceString("source.type.unknown"), new Object[] { type }));
            }
            for(Source[] sources = library.sources.clone(), int index = sources.length; index-- > 0; ) sources[index].loadFromFileStream();
        }
    }

    private void findBinarySources(Library library, String relativePath) throws IOException {
        with(fldParentProject.excludes, library.fileSystem, findFirst(library.directoryPath + relativePath)) try
        {
            int length = getObjectNameMaximumLength();
            do
            {
                String objectName = name;
                if(!".".equals(objectName) && !"..".equals(objectName) && !contains(objectName))
                {
                    if(directory)
                    {
                        findBinarySources(library, (new StringBuilder(length) + relativePath + objectName + '/').toString());
                        continue;
                    }
                    if(Project.isBinarySourceFileName(objectName))
                    {
                        library.createSource(relativePath + objectName, BINARY_SOURCE);
                    }
                }
            } while(findNext());
        } finally
        {
            close();
        }
    }

    private void findTypeSources(Library library, String relativePath) throws IOException {
        with(fldParentProject.excludes, library.fileSystem, findFirst(library.directoryPath + relativePath)) try
        {
            int length = getObjectNameMaximumLength();
            do
            {
                String objectName = name;
                if(!".".equals(objectName) && !"..".equals(objectName) && !contains(objectName))
                {
                    if(directory)
                    {
                        findTypeSources(library, (new StringBuilder(length) + relativePath + objectName + '/').toString());
                        continue;
                    }
                    if(Project.isTypeSourceFileName(objectName))
                    {
                        library.createSource(relativePath + objectName, TEXT_SOURCE);
                    }
                }
            } while(findNext());
        } finally
        {
            close();
        }
    }

    private void findPackageSources(Library library) throws IOException {
        with(fldParentProject.excludes, library.fileSystem.findFirst(library.directoryPath)) try
        {
            do
            {
                String objectName = name;
                if(!".".equals(objectName) && !"..".equals(objectName) && !contains(objectName) && !directory && Project.isPackageSourceFileName(objectName))
                {
                    library.createSource(objectName, TEXT_SOURCE);
                }
            } while(findNext());
        } finally
        {
            close();
        }
    }
}