/*
Компилятор языка программирования
Объектно-ориентированный продвинутый векторный транслятор
Copyright © 2021, 2024, 2026 Малик Разработчик
Это свободная программа: вы можете перераспространять ее и/или изменять
ее на условиях Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она будет полезной,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Стандартной
общественной лицензии GNU.
Вы должны были получить копию Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<https://www.gnu.org/licenses/>.
*/
package ru.malik.elaborarer.avtoo.avtc;
import avt.io.*;
import avtx.application.*;
import platform.independent.filesystem.*;
import platform.independent.osservices.*;
import platform.independent.streamformat.*;
import platform.independent.streamformat.text.*;
import ru.malik.elaborarer.avtoo.generator.*;
import ru.malik.elaborarer.avtoo.lang.*;
import ru.malik.elaborarer.avtoo.compiler.StringArray;
public final class AVTC(ConsoleApp, StreamFormatManager, AVTOOConstants)
{
public static String[] loadParametersFrom(ByteReader stream) throws Exception {
TextDecoder decoder = (TextDecoder) createDecoder("text/plain");
decoder.loadFromInputStream(stream);
String text = decoder.getText();
if(text != null && text.startsWith("\ufeff")) text = text.substring(1);
return text.split();
}
public static String[] loadParametersFrom(FileSystem fileSystem, String fileName) throws Exception {
ByteReader stream = fileSystem.openFileForRead(fileName);
try
{
return loadParametersFrom(stream);
} finally
{
stream.close();
}
}
public () { }
public int main(String[] arguments) {
/* результат выполнения */
int result = 0;
/* переменные для хранения аргументов командной строки */
int level = BinarySourceGenerator.CLASS;
int debug = 0;
String classpathName = "";
String projectDirectory = null;
/* стандартные потоки вывода */
PrintStream stdOut = System.out;
PrintStream stdErr = System.err;
/* чтение аргументов командной строки */
for(String prefix, int length = arguments.length, int index = 1; index < length; index++)
{
String arg = arguments[index];
String low = arg.toLowerCase();
if(low.startsWith(prefix = "--level="))
{
String value = low.substring(prefix.length);
if("pack".equals(value))
{
level = BinarySourceGenerator.PACKAGE;
continue;
}
if("lib".equals(value))
{
level = BinarySourceGenerator.LIBRARY;
}
continue;
}
if(low.startsWith(prefix = "--debug="))
{
String value = low.substring(prefix.length);
if("code".equals(value))
{
debug = 1;
continue;
}
if("lexemes".equals(value))
{
debug = 2;
continue;
}
if("both".equals(value))
{
debug = 3;
continue;
}
if("trace".equals(value))
{
debug = 4;
continue;
}
if("code+trace".equals(value) || "trace+code".equals(value))
{
debug = 5;
continue;
}
if("lexemes+trace".equals(value) || "trace+lexemes".equals(value))
{
debug = 6;
continue;
}
if("both+trace".equals(value) || "trace+both".equals(value))
{
debug = 7;
}
continue;
}
if(projectDirectory == null)
{
projectDirectory = arg;
continue;
}
classpathName = arg;
}
try
{
/* папки процесса */
String workingDirectory = Process.current().workingDirectory;
String processDirectory = FileSystemRoot.toObjectPath(arguments[0]);
processDirectory = processDirectory.substring(0, processDirectory.lastIndexOf(FileSystem.DIRECTORY_SEPARATOR) + 1);
/* вывод приветствия */
stdOut.printlnf(package.getResourceString("title"), new Object[] { VERSION });
/* папка проекта */
if(projectDirectory == null)
{
stdOut.println(package.getResourceString("help"));
return 1;
}
if(FileSystemRoot.isInternalPathFull(projectDirectory))
{
projectDirectory = FileSystemRoot.toObjectPath(projectDirectory);
} else
{
projectDirectory = workingDirectory + FileSystemRoot.get(workingDirectory).fileSystem.toObjectName(projectDirectory);
}
if(!projectDirectory.endsWith("" + FileSystem.DIRECTORY_SEPARATOR))
{
projectDirectory = projectDirectory + FileSystem.DIRECTORY_SEPARATOR;
}
String projectRootPath;
FileSystem projectFileSystem;
with(FileSystemRoot.get(projectDirectory))
{
projectRootPath = path;
projectDirectory = projectDirectory.substring(projectRootPath.length);
projectFileSystem = fileSystem;
}
/* файл параметров проекта */
if(classpathName.length > 0) classpathName = projectFileSystem.toObjectName(classpathName);
/* процесс компиляции */
/* время компиляции */
long time = System.currentTimeInMillis();
/* параметры компиляции */
String[] parameters = loadParametersFrom(projectFileSystem, (new StringBuilder()).append(projectDirectory).append(classpathName).append(".classpath").toString());
/* переменные для хранения параметров компиляции */
boolean isLibrary = false;
boolean isReflect = false;
StringArray excludes = new StringArray();
StringArray libraries = new StringArray();
/* чтение параметров компиляции */
for(int length = parameters.length, int index = 0; index < length; index++)
{
String parameter = parameters[index];
/* комментарии */
int chpos = parameter.indexOf(';');
if(chpos >= 0) parameter = parameter.substring(0, chpos);
/* параметры компиляции */
if((chpos = parameter.indexOf('=')) >= 0)
{
String prefix = parameter.substring(0, chpos).trim();
String value = parameter.substring(1 + chpos).trim();
if(prefix.equals("pointer-size"))
{
/* устаревший параметр */
continue;
}
if(prefix.equals("library"))
{
isLibrary = !value.equals("0") && !value.isEmpty();
continue;
}
if(prefix.equals("reflect"))
{
isReflect = !value.equals("0") && !value.isEmpty();
continue;
}
}
/* исключаемые из обработки файлы исходного кода */
String prefix = "-";
if((parameter = parameter.trim()).startsWith(prefix))
{
excludes.append(parameter.substring(prefix.length).trim());
continue;
}
if(!parameter.isEmpty()) libraries.append(parameter);
}
parameters = null;
/* создание экземпляра компилятора */
CodeGenerator programme = isLibrary ? (
(CodeGenerator) (new BinarySourceGenerator() { level = level })
) : (
(CodeGenerator) (new AssemblerSourceGenerator(isReflect, classpathName.replaceAll(FileSystem.DIRECTORY_SEPARATOR, '.')))
);
programme.documentationEnabled = (debug & 2) != 0;
/* исключаемые из обработки файлы текстового исходного кода */
for(StringArray destination = programme.excludes, int length = excludes.length, int index = 0; index < length; index++) destination.append(excludes[index]);
excludes = null;
/* используемые проектом библиотеки */
for(int length = libraries.length, int index = 0; index < length; index++)
{
FileSystem libraryFileSystem;
String libraryDirectory = libraries[index];
if(!libraryDirectory.startsWith("" + FileSystem.DIRECTORY_SEPARATOR)) libraryDirectory = processDirectory + libraryDirectory;
if(!libraryDirectory.endsWith("" + FileSystem.DIRECTORY_SEPARATOR)) libraryDirectory = libraryDirectory + FileSystem.DIRECTORY_SEPARATOR;
with(FileSystemRoot.get(libraryDirectory))
{
libraryDirectory = libraryDirectory.substring(path.length);
libraryFileSystem = fileSystem;
}
programme.createLibrary(libraryFileSystem, libraryDirectory, false);
}
libraries = null;
/* создание библиотеки проекта */
Library projectLibrary = programme.createLibrary(projectFileSystem, projectDirectory, !isLibrary);
try
{
/* компиляция проекта */
programme.compile();
} catch(RuntimeException exception)
{
exception.printStackTrace();
result = 4;
} catch(Exception exception)
{
if((debug & 4) != 0)
{
exception.printStackTrace();
} else
{
stdErr.println(exception);
}
result = exception instanceof CompilerException ? 2 : 3;
}
/* вывод времени и результатов компиляции */
time = (System.currentTimeInMillis() - time) / 100;
String overwritten = programme.overwritten;
if(result != 0 || overwritten == null || overwritten.isEmpty())
{
stdOut.printlnf(package.getResourceString("time.only"), new Object[] { Long.toString(time / 10), Long.toString(time % 10) });
} else
{
overwritten = FileSystemRoot.toInternalPath(projectRootPath + overwritten);
stdOut.printlnf(package.getResourceString("time.overwritten"), new Object[] { Long.toString(time / 10), Long.toString(time % 10), overwritten });
}
/* отладочная печать */
if((debug & 3) != 0)
{
Object monitor = new Object();
PrintThread lexThread = null;
PrintThread codeThread = null;
if((debug & 1) != 0)
{
(codeThread = new PrintCodeThread(monitor, projectFileSystem, projectDirectory + "debug.code.txt", programme)).start();
}
if((debug & 2) != 0)
{
(lexThread = new PrintLexemesThread(monitor, projectFileSystem, projectDirectory + "debug.lexemes.txt", projectLibrary)).start();
}
synchronized(monitor)
{
do
{
try
{
monitor.wait();
} catch(InterruptedException exception)
{
exception.printStackTrace();
}
} while(codeThread != null && !codeThread.isTerminated() || lexThread != null && !lexThread.isTerminated());
}
}
} catch(IOException exception)
{
exception.printStackTrace();
result = 3;
} catch(Exception exception)
{
exception.printStackTrace();
result = 4;
}
return result;
}
}