/*
Компилятор языка программирования
Объектно-ориентированный продвинутый векторный транслятор
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();
}
}
}