AVTC.avt

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

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

    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;
    }
}