AVTC.avt

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

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

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

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

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

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

package ru.malik.elaborarer.avtoo.avtc;

import avt.io.*;
import avt.lang.array.*;
import avtx.application.*;
import platform.independent.filesystem.*;
import platform.independent.streamformat.*;
import platform.independent.streamformat.text.*;
import ru.malik.elaborarer.avtoo.compiler.StringArray;
import ru.malik.elaborarer.avtoo.generator.*;
import ru.malik.elaborarer.avtoo.lang.*;

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 projectDirectory = null;
        String classpathName = "";

        /* стандартный вывод */
        PrintStream standardOutput = System.out;

        /* чтение аргументов командной строки */
        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
        {
            /* файловая система */
            FileSystem fileSystem = Platform.instance.localFileSystem;

            /* папки процесса */
            String currentDirectory = currentDirectory;
            String processDirectory = fileSystem.toObjectName(arguments[0]);
            processDirectory = processDirectory.substring(0, processDirectory.lastIndexOf(FileSystem.DIRECTORY_SEPARATOR) + 1);

            /* вывод приветствия */
            standardOutput.printlnf(package.getResourceString("title"), new Object[] { VERSION });

            /* папка проекта */
            if(projectDirectory == null)
            {
                standardOutput.println(package.getResourceString("help"));
                return 1;
            }
            if(fileSystem.isInternalNameFull(projectDirectory))
            {
                projectDirectory = fileSystem.toObjectName(projectDirectory);
            } else
            {
                projectDirectory = (new StringBuilder() + currentDirectory + FileSystem.DIRECTORY_SEPARATOR + fileSystem.toObjectName(projectDirectory)).toString();
            }
            if(!projectDirectory.endsWith("" + FileSystem.DIRECTORY_SEPARATOR))
            {
                projectDirectory = projectDirectory + FileSystem.DIRECTORY_SEPARATOR;
            }

            /* файл параметров проекта */
            if(classpathName.length > 0) classpathName = fileSystem.toObjectName(classpathName);
            String classpathFile = (new StringBuilder() + projectDirectory + classpathName + ".classpath").toString();

            /* процесс компиляции */

            /* время компиляции */
            long time = System.currentTimeInMillis();

            /* параметры компиляции */
            String[] parameters = loadParametersFrom(fileSystem, classpathFile);

            /* переменные для хранения параметров компиляции */
            boolean isLibrary = false;
            boolean isReflect = false;
            int pointerSize = BITS64;
            StringArray excludes = new StringArray();
            StringArray libraries = new StringArray();

            /* чтение параметров компиляции */
            for(String prefix, int length = parameters.length, int index = 0; index < length; index++)
            {
                String parameter = parameters[index].trim();
                if(parameter.startsWith(prefix = "pointer-size="))
                {
                    String value = parameter.substring(prefix.length);
                    pointerSize = "32".equals(value) ? BITS32 : BITS64;
                    continue;
                }
                if(parameter.startsWith(prefix = "reflect="))
                {
                    String value = parameter.substring(prefix.length);
                    isReflect = !"0".equals(value) && !value.isEmpty();
                    continue;
                }
                if(parameter.startsWith(prefix = "library="))
                {
                    String value = parameter.substring(prefix.length);
                    isLibrary = !"0".equals(value) && !value.isEmpty();
                    continue;
                }
                if(parameter.startsWith(prefix = "-"))
                {
                    excludes.append(parameter.substring(prefix.length));
                    continue;
                }
                if(!parameter.isEmpty())
                {
                    libraries.append(parameter);
                }
            }
            parameters = null;

            /* создание экземпляра компилятора */
            CodeGenerator programme = isLibrary ? (
                (CodeGenerator) new BinarySourceGenerator(pointerSize) { level = level }
            ) : (
                (CodeGenerator) new AssemblerSourceGenerator(pointerSize, isReflect, classpathName.replaceAll(FileSystem.DIRECTORY_SEPARATOR, '.'))
            );
            programme.documentationEnabled = (debug & 2) != 0;
            programme.documentationLexer.lineEndingEnabled = false;

            /* исключаемые из обработки файлы текстового исходного кода */
            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++)
            {
                String libraryDirectory = libraries[index];
                if(!libraryDirectory.startsWith("" + FileSystem.DIRECTORY_SEPARATOR)) libraryDirectory = processDirectory + libraryDirectory;
                if(!libraryDirectory.endsWith("" + FileSystem.DIRECTORY_SEPARATOR)) libraryDirectory = libraryDirectory + FileSystem.DIRECTORY_SEPARATOR;
                programme.createLibrary(fileSystem, libraryDirectory, false);
            }
            libraries = null;

            /* создание библиотеки проекта */
            Library project = programme.createLibrary(fileSystem, projectDirectory, !isLibrary);

            try
            {
                /* компиляция проекта */
                programme.compile();
            }
            catch(RuntimeException exception)
            {
                exception.printStackTrace();
                result = 4;
            }
            catch(Exception exception)
            {
                if((debug & 4) != 0)
                {
                    exception.printStackTrace(standardOutput);
                } else
                {
                    standardOutput.println(exception);
                }
                result = exception instanceof CompilerException ? 2 : 3;
            }

            /* вывод времени и результатов компиляции */
            time = (System.currentTimeInMillis() - time) / 100;
            String overwritten = programme.overwritten;
            if(result != 0 || overwritten == null || overwritten.isEmpty())
            {
                standardOutput.printlnf(package.getResourceString("time.only"), new Object[] { Long.toString(time / 10), Long.toString(time % 10) });
            } else
            {
                standardOutput.printlnf(package.getResourceString("time.overwritten"), new Object[] { Long.toString(time / 10), Long.toString(time % 10), fileSystem.toInternalName(overwritten) });
            }

            /* отладочная печать */
            if((debug & 3) != 0)
            {
                Object monitor = new Object();
                AVTCPrintThread codeThread = null;
                AVTCPrintThread lexemesThread = null;
                if((debug & 1) != 0)
                {
                    (codeThread = new AVTCPrintCodeThread(monitor, fileSystem, projectDirectory + "debug.code.txt", programme)).start();
                }
                if((debug & 2) != 0)
                {
                    (lexemesThread = new AVTCPrintLexemesThread(monitor, fileSystem, projectDirectory + "debug.lexemes.txt", project)).start();
                }
                synchronized(monitor)
                {
                    do
                    {
                        try
                        {
                            monitor.wait();
                        }
                        catch(InterruptedException exception)
                        {
                            exception.printStackTrace();
                        }
                    } while(codeThread != null && !codeThread.isTerminated() || lexemesThread != null && !lexemesThread.isTerminated());
                }
            }
        }
        catch(IOException exception)
        {
            exception.printStackTrace();
            result = 3;
        }
        catch(Exception exception)
        {
            exception.printStackTrace();
            result = 4;
        }
        return result;
    }
}

class AVTCPrintThread(Thread, Runnable)
{
    protected final FileSystem fldFileSystem;
    protected final String fldFileName;
    private boolean fldTerminated;
    private final Object fldMonitor;

    public (Object monitor, FileSystem fileSystem, String fileName) {
        fldFileSystem = fileSystem != null ? fileSystem : Platform.instance.localFileSystem;
        fldFileName = fileName != null ? fileName : "";
        fldMonitor = monitor;
    }

    public boolean isTerminated() { return fldTerminated; }

    protected final void terminate() {
        synchronized with(fldMonitor)
        {
            if(!fldTerminated)
            {
                fldTerminated = true;
                notify();
            }
        }
    }
}

class AVTCPrintCodeThread(AVTCPrintThread, Runnable, AVTOOConstants)
{
    private static void print(FileSystem fileSystem, String fileName, Programme programme) throws IOException {
        if(fileSystem.isObjectExists(fileName)) fileSystem.deleteFile(fileName);
        PrintStream debugOutput = new PrintStream(fileSystem.createFile(fileName));
        try
        {
            StringBuilder debugBuilder = new StringBuilder();
            for(LibraryArray libraries = programme.libraries, int llength = libraries.length, int lindex = 0; lindex < llength; lindex++)
            {
                Library library = libraries[lindex];
                debugOutput.println(library.specialSimpleName);
                for(int plength = library.length, int pindex = 0; pindex < plength; pindex++)
                {
                    Package pack = library[pindex];
                    debugOutput.println(debugBuilder + "\t" + attributesToString(pack) + namesToString(pack));
                    debugBuilder.clear();
                    for(int tlength = pack.length, int tindex = 0; tindex < tlength; tindex++)
                    {
                        Type type = pack[tindex];
                        if(!(type instanceof ClassType))
                        {
                            debugOutput.println(debugBuilder + "\t\t" + attributesToString(type) + namesToString(type));
                        } else
                        {
                            debugOutput.println(debugBuilder + "\t\t" + attributesToString(type) + supertypesToString((ClassType) type) + namesToString(type));
                        }
                        debugBuilder.clear();
                        if(type instanceof ClassType) for(ClassType clas = (ClassType) type, int mlength = clas.length, int mindex = 0; mindex < mlength; mindex++)
                        {
                            Node root = null;
                            Member member = clas[mindex];
                            debugBuilder + "\t\t\t" + attributesToString(member);
                            if(member instanceof Callable) with((Callable) member)
                            {
                                debugBuilder + arguments.toFullString();
                                if(member instanceof Method) with((Method) member) for(int elength = getThrowablesLength(), int eindex = 0; eindex < elength; eindex++)
                                {
                                    debugBuilder + (eindex < 1 ? " throws " : ", ") + getThrowableTypeAt(eindex).specialCanonicalName;
                                }
                                Code code = code;
                                if(code != null) root = code.root;
                            }
                            else if(member instanceof Field) with((Field) member)
                            {
                                Constant value = value;
                                if(value != null) debugBuilder + " = " + value;
                            }
                            else if(member instanceof Property) with((Property) member)
                            {
                                Method index = indexSynthetic;
                                Method read = readSynthetic;
                                Method write = writeSynthetic;
                                Method stored = storedSynthetic;
                                debugBuilder + " { ";
                                if(index != null)
                                {
                                    Member pmember = indexMember;
                                    Constant constant = indexConstant;
                                    debugBuilder + "index = " + (pmember != null ? pmember.specialSimpleName : constant == null ? index.specialSimpleName : constant.toString()) + ", ";
                                }
                                if(read == null)
                                {
                                    Member pmember = writeMember;
                                    debugBuilder + "write = " + (pmember != null ? pmember.specialSimpleName : write.specialSimpleName);
                                }
                                else if(write == null)
                                {
                                    Member pmember = readMember;
                                    Constant constant = readConstant;
                                    debugBuilder + "read = " + (pmember != null ? pmember.specialSimpleName : constant == null ? read.specialSimpleName : constant.toString());
                                }
                                else
                                {
                                    Member pmember = readMember;
                                    Constant constant = readConstant;
                                    debugBuilder + "read = " + (pmember != null ? pmember.specialSimpleName : constant == null ? read.specialSimpleName : constant.toString()) + ", ";
                                    pmember = writeMember;
                                    debugBuilder + "write = " + (pmember != null ? pmember.specialSimpleName : write.specialSimpleName);
                                }
                                if(stored != null)
                                {
                                    Member pmember = storedMember;
                                    Constant constant = storedConstant;
                                    debugBuilder + ", stored = " + (pmember != null ? pmember.specialSimpleName : constant == null ? stored.specialSimpleName : constant.toString());
                                }
                                debugBuilder + " }";
                            }
                            debugOutput.println(debugBuilder + namesToString(member));
                            debugBuilder.clear();
                            if(root != null) for(Code code = root.parentCode, int margin = 4, int clength = code.length, int cindex = 0; cindex < clength; cindex++)
                            {
                                Node node = code[cindex];
                                for(int tab = margin; tab-- > 0; debugBuilder + '\t');
                                int instruction = node.instruction;
                                Type typeRef = node.type;
                                String typeAsString = typeRef == null ? "-" : typeRef.toString();
                                String instructionAsString = null;
                                switch(instruction)
                                {
                                case CLASS                 : instructionAsString = "CLASS"; break;
                                case INSTANCEOF            : instructionAsString = "INSTANCEOF"; break;
                                case IF                    : instructionAsString = "IF"; break;
                                case SWITCH                : instructionAsString = "SWITCH"; break;
                                case BRANCH                : instructionAsString = "BRANCH"; break;
                                case CASE                  : instructionAsString = "CASE"; break;
                                case DEFAULT               : instructionAsString = "DEFAULT"; break;
                                case LABEL                 : instructionAsString = "LABEL"; break;
                                case DO                    : instructionAsString = "DO"; break;
                                case FOR                   : instructionAsString = "FOR"; break;
                                case WHILE                 : instructionAsString = "WHILE"; break;
                                case BLOCK                 : instructionAsString = "BLOCK"; break;
                                case JUMP                  : instructionAsString = "JUMP"; break;
                                case BREAK                 : instructionAsString = "BREAK"; break;
                                case CONTINUE              : instructionAsString = "CONTINUE"; break;
                                case RETURN                : instructionAsString = "RETURN"; break;
                                case THROW                 : instructionAsString = "THROW"; break;
                                case BOUND                 : instructionAsString = "BOUND"; break;
                                case BEGIN                 : instructionAsString = "BEGIN"; break;
                                case END                   : instructionAsString = "END"; break;
                                case TRY                   : instructionAsString = "TRY"; break;
                                case CATCH                 : instructionAsString = "CATCH"; break;
                                case INVOKE_FINALLY        : instructionAsString = "INVOKE_FINALLY"; break;
                                case CLINIT_TRY_LOCK       : instructionAsString = "CLINIT_TRY_LOCK"; break;
                                case CLINIT_UNLOCK         : instructionAsString = "CLINIT_UNLOCK"; break;
                                case FINALLY_ENTER         : instructionAsString = "FINALLY_ENTER"; break;
                                case FINALLY_LEAVE         : instructionAsString = "FINALLY_LEAVE"; break;
                                case MONITOR_ENTER         : instructionAsString = "MONITOR_ENTER"; break;
                                case MONITOR_LEAVE         : instructionAsString = "MONITOR_LEAVE"; break;
                                case METHOD_ENTER          : instructionAsString = "METHOD_ENTER"; break;
                                case METHOD_LEAVE          : instructionAsString = "METHOD_LEAVE"; break;
                                case LOAD_CONST            : instructionAsString = "LOAD_CONST"; break;
                                case LOAD_LOCAL            : instructionAsString = "LOAD_LOCAL"; break;
                                case LOAD_INTERRUPT        : instructionAsString = "LOAD_INTERRUPT"; break;
                                case LOAD_STATIC           : instructionAsString = "LOAD_STATIC"; break;
                                case READ_ELEMENT          : instructionAsString = "READ_ELEMENT"; break;
                                case READ_COMPONENT        : instructionAsString = "READ_COMPONENT"; break;
                                case READ_FIELD            : instructionAsString = "READ_FIELD"; break;
                                case READ_SPECIAL          : instructionAsString = "READ_SPECIAL"; break;
                                case READ_PROPERTY         : instructionAsString = "READ_PROPERTY"; break;
                                case SWAP                  : instructionAsString = "SWAP"; break;
                                case DUP1                  : instructionAsString = "DUP1"; break;
                                case DUP1X1                : instructionAsString = "DUP1X1"; break;
                                case DUP1X2                : instructionAsString = "DUP1X2"; break;
                                case DUP2                  : instructionAsString = "DUP2"; break;
                                case INVOKE_STATIC         : instructionAsString = "INVOKE_STATIC"; break;
                                case INVOKE_SPECIAL        : instructionAsString = "INVOKE_SPECIAL"; break;
                                case INVOKE_VIRTUAL        : instructionAsString = "INVOKE_VIRTUAL"; break;
                                case INVOKE_SERVICE        : instructionAsString = "INVOKE_SERVICE"; break;
                                case NEW_VECTOR            : instructionAsString = "NEW_VECTOR"; break;
                                case NEW_ARRAY             : instructionAsString = "NEW_ARRAY"; break;
                                case NEW_ARRAY_MONO        : instructionAsString = "NEW_ARRAY_MONO"; break;
                                case NEW_ARRAY_MULTI       : instructionAsString = "NEW_ARRAY_MULTI"; break;
                                case NEW_INSTANCE          : instructionAsString = "NEW_INSTANCE"; break;
                                case CAST_TO               : instructionAsString = "CAST_TO"; break;
                                case INC_LOCAL             : instructionAsString = "INC_LOCAL"; break;
                                case DEC_LOCAL             : instructionAsString = "DEC_LOCAL"; break;
                                case INC_PRED_LOAD_LOCAL   : instructionAsString = "INC_PRED_LOAD_LOCAL"; break;
                                case DEC_PRED_LOAD_LOCAL   : instructionAsString = "DEC_PRED_LOAD_LOCAL"; break;
                                case INC_POST_LOAD_LOCAL   : instructionAsString = "INC_POST_LOAD_LOCAL"; break;
                                case DEC_POST_LOAD_LOCAL   : instructionAsString = "DEC_POST_LOAD_LOCAL"; break;
                                case BOOL_NOT              : instructionAsString = "BOOL_NOT"; break;
                                case BOOL_AND              : instructionAsString = "BOOL_AND"; break;
                                case BOOL_OR               : instructionAsString = "BOOL_OR"; break;
                                case BOOL_COND             : instructionAsString = "BOOL_COND"; break;
                                case REF_EQ                : instructionAsString = "REF_EQ"; break;
                                case REF_NE                : instructionAsString = "REF_NE"; break;
                                case REF_IS_NULL           : instructionAsString = "REF_IS_NULL"; break;
                                case REF_IS_OBJECT         : instructionAsString = "REF_IS_OBJECT"; break;
                                case TEST_EQZ              : instructionAsString = "TEST_EQZ"; break;
                                case TEST_NEZ              : instructionAsString = "TEST_NEZ"; break;
                                case O_BIT_NOT             : instructionAsString = "O_BIT_NOT"; break;
                                case O_BIT_AND             : instructionAsString = "O_BIT_AND"; break;
                                case O_BIT_OR              : instructionAsString = "O_BIT_OR"; break;
                                case O_BIT_XOR             : instructionAsString = "O_BIT_XOR"; break;
                                case O_SCAL_NEG            : instructionAsString = "O_SCAL_NEG"; break;
                                case O_SCAL_MUL            : instructionAsString = "O_SCAL_MUL"; break;
                                case O_SCAL_DIV            : instructionAsString = "O_SCAL_DIV"; break;
                                case O_SCAL_DIVU           : instructionAsString = "O_SCAL_DIVU"; break;
                                case O_SCAL_REM            : instructionAsString = "O_SCAL_REM"; break;
                                case O_SCAL_REMU           : instructionAsString = "O_SCAL_REMU"; break;
                                case O_SCAL_ADD            : instructionAsString = "O_SCAL_ADD"; break;
                                case O_SCAL_SUB            : instructionAsString = "O_SCAL_SUB"; break;
                                case O_SCAL_SHR            : instructionAsString = "O_SCAL_SHR"; break;
                                case O_SCAL_SHRU           : instructionAsString = "O_SCAL_SHRU"; break;
                                case O_SCAL_SHL            : instructionAsString = "O_SCAL_SHL"; break;
                                case O_SCAL_GT             : instructionAsString = "O_SCAL_GT"; break;
                                case O_SCAL_GE             : instructionAsString = "O_SCAL_GE"; break;
                                case O_SCAL_LT             : instructionAsString = "O_SCAL_LT"; break;
                                case O_SCAL_LE             : instructionAsString = "O_SCAL_LE"; break;
                                case O_SCAL_EQ             : instructionAsString = "O_SCAL_EQ"; break;
                                case O_SCAL_NE             : instructionAsString = "O_SCAL_NE"; break;
                                case O_VECT_LUP            : instructionAsString = "O_VECT_LUP"; break;
                                case O_VECT_UUP            : instructionAsString = "O_VECT_UUP"; break;
                                case O_VECT_PCK            : instructionAsString = "O_VECT_PCK"; break;
                                case O_VECT_NEG            : instructionAsString = "O_VECT_NEG"; break;
                                case O_VECT_MUL            : instructionAsString = "O_VECT_MUL"; break;
                                case O_VECT_DIV            : instructionAsString = "O_VECT_DIV"; break;
                                case O_VECT_ADD            : instructionAsString = "O_VECT_ADD"; break;
                                case O_VECT_SUB            : instructionAsString = "O_VECT_SUB"; break;
                                case O_VECT_SHR            : instructionAsString = "O_VECT_SHR"; break;
                                case O_VECT_SHRU           : instructionAsString = "O_VECT_SHRU"; break;
                                case O_VECT_SHL            : instructionAsString = "O_VECT_SHL"; break;
                                case O_VECT_GT             : instructionAsString = "O_VECT_GT"; break;
                                case O_VECT_GE             : instructionAsString = "O_VECT_GE"; break;
                                case O_VECT_LT             : instructionAsString = "O_VECT_LT"; break;
                                case O_VECT_LE             : instructionAsString = "O_VECT_LE"; break;
                                case O_VECT_EQ             : instructionAsString = "O_VECT_EQ"; break;
                                case O_VECT_NE             : instructionAsString = "O_VECT_NE"; break;
                                case O_VECT_HMUL           : instructionAsString = "O_VECT_HMUL"; break;
                                case O_VECT_HMULU          : instructionAsString = "O_VECT_HMULU"; break;
                                case O_VECT_SADD           : instructionAsString = "O_VECT_SADD"; break;
                                case O_VECT_SADDU          : instructionAsString = "O_VECT_SADDU"; break;
                                case O_VECT_SSUB           : instructionAsString = "O_VECT_SSUB"; break;
                                case O_VECT_SSUBU          : instructionAsString = "O_VECT_SSUBU"; break;
                                case STORE_LOCAL           : instructionAsString = "STORE_LOCAL"; break;
                                case DECLARE_WITH          : instructionAsString = "DECLARE_WITH"; break;
                                case DECLARE_LOCAL         : instructionAsString = "DECLARE_LOCAL"; break;
                                case STORE_STATIC          : instructionAsString = "STORE_STATIC"; break;
                                case WRITE_COMPONENT       : instructionAsString = "WRITE_COMPONENT"; break;
                                case WRITE_FIELD           : instructionAsString = "WRITE_FIELD"; break;
                                case WRITE_SPECIAL         : instructionAsString = "WRITE_SPECIAL"; break;
                                case WRITE_PROPERTY        : instructionAsString = "WRITE_PROPERTY"; break;
                                case EXCEPT_ENTER          : instructionAsString = "EXCEPT_ENTER"; break;
                                case EXCEPT_TRY            : instructionAsString = "EXCEPT_TRY"; break;
                                case EXCEPT_CATCH          : instructionAsString = "EXCEPT_CATCH"; break;
                                case EXCEPT_FINALLY        : instructionAsString = "EXCEPT_FINALLY"; break;
                                case EXCEPT_LEAVE          : instructionAsString = "EXCEPT_LEAVE"; break;
                                default                    : instructionAsString = "<UNKNOWN>";
                                }
                                int order = node.order;
                                int2 location = node.location + new byte2 { 1, 1 };
                                debugBuilder + "0x" + Long.toHexString(System.identityHashCode(node));
                                if(order >= 0)
                                {
                                    int debug = node.debugIndex;
                                    int label = node.labelIndex;
                                    debugBuilder + '(' + order;
                                    if(debug >= 0)
                                    {
                                        debugBuilder + ", D." + debug;
                                    }
                                    else if(label >= 0)
                                    {
                                        debugBuilder + ", L." + label;
                                    }
                                    debugBuilder + ')';
                                }
                                debugBuilder + String.format("[%0:5%:%1:3%] %2% %3%", new Object[] {
                                    Int.toString(location[0]), Int.toString(location[1]), typeAsString, !node.weak ? instructionAsString : "(w)" + instructionAsString
                                });
                                label1:
                                {
                                    TableItem operand = node.operand1;
                                    if(operand != null)
                                    {
                                        debugBuilder + '(';
                                        if((instruction == DECLARE_LOCAL || instruction == DECLARE_WITH) && operand instanceof TypedItem)
                                        {
                                            debugBuilder + ((TypedItem) operand).type + ' ';
                                        }
                                        debugBuilder + operand;
                                        if((operand = node.operand2) != null)
                                        {
                                            debugBuilder + ", " + operand;
                                        }
                                        debugBuilder + ')';
                                        break label1;
                                    }
                                    Object reference = node.reference1;
                                    if(reference != null)
                                    {
                                        debugBuilder + '(' + (!(reference instanceof Node) ? reference.toString() : "0x" + Long.toHexString(System.identityHashCode(reference)));
                                        if((reference = node.reference2) != null)
                                        {
                                            debugBuilder + ", " + (!(reference instanceof Node) ? reference.toString() : "0x" + Long.toHexString(System.identityHashCode(reference)));
                                        }
                                        debugBuilder + ')';
                                    }
                                }
                                int ordert;
                                int jlength = node.getJumpCasesLength();
                                if(jlength > 0 || instruction == JUMP || instruction == RETURN)
                                {
                                    Node target = node.jumpDefault;
                                    debugBuilder + "[default" + (target == null ? ">null" : ">0x" + Long.toHexString(System.identityHashCode(target)));
                                    for(int jindex = 0; jindex < jlength; jindex++)
                                    {
                                        target = node.getJumpCaseNodeAt(jindex);
                                        debugBuilder + ", " + Int.toString(node.getJumpCaseValueAt(jindex)) + (target == null ? ">null" : ">0x" + Long.toHexString(System.identityHashCode(target)));
                                    }
                                    debugBuilder + "]";
                                }
                                debugOutput.println(debugBuilder);
                                debugBuilder.clear();
                            }
                        }
                    }
                }
            }
        } finally
        {
            debugOutput.close();
        }
    }

    private static String attributesToString(ReflectItem item) {
        int attributesAsNumber = item.attributes;
        StringBuilder attributesAsString = new StringBuilder();
        switch(attributesAsNumber & MASK_VISIBILITY)
        {
        case PRIVATE:
            attributesAsString + "private ";
            break;
        case RESERVED_PACKAGE:
        case PACKAGE:
            attributesAsString + "package ";
            break;
        case PROTECTED:
            attributesAsString + "protected ";
            break;
        case PUBLIC:
            attributesAsString + "public ";
            break;
        case PUBLISHED:
            attributesAsString + "published ";
        }
        if((attributesAsNumber & ATTR_SYNTHETIC) != 0)
        {
            attributesAsString + "synthetic ";
        }
        if((attributesAsNumber & ATTR_ABSTRACT) != 0)
        {
            attributesAsString + "abstract ";
        }
        if((attributesAsNumber & ATTR_STATIC) != 0)
        {
            attributesAsString + "static ";
        }
        if((attributesAsNumber & ATTR_FINAL) != 0)
        {
            attributesAsString + "final ";
        }
        if(item instanceof Package)
        {
            attributesAsString + "package ";
        }
        else if(item instanceof Type) switch((attributesAsNumber & MASK_TYPE) >> 5)
        {
        case ATTR_PRIMITIVE >> 5:
            attributesAsString + "primitive ";
            break;
        case ATTR_SERVICE >> 5:
            attributesAsString + "service ";
            break;
        case ATTR_STRUCT >> 5:
            attributesAsString + "struct ";
            break;
        case ATTR_INTERFACE >> 5:
            attributesAsString + "interface ";
            break;
        default:
            attributesAsString + "class ";
        }
        if((attributesAsNumber & ATTR_NATIVE) != 0)
        {
            attributesAsString + "native ";
        }
        if((attributesAsNumber & ATTR_INTERRUPT) != 0)
        {
            attributesAsString + "interrupt ";
        }
        if((attributesAsNumber & ATTR_SYNCHRONIZED) != 0)
        {
            attributesAsString + "synchronized ";
        }
        if(item instanceof TypedItem)
        {
            attributesAsString + ((TypedItem) item).type.specialCanonicalName + ' ';
        }
        return (attributesAsString + item.specialSimpleName).toString();
    }

    private static String namesToString(ReflectItem item) {
        StringBuilder result = new StringBuilder() + " { ";
        if(item instanceof RequiredReflectItem)
        {
            result + "spec canonical = " + ((RequiredReflectItem) item).specialCanonicalName + ", ";
        }
        result + "recompilable = " + item.recompilableName + ", fasm simple = " + item.fasmSimpleName + ", fasm full = " + item.fasmFullName;
        if(item instanceof Field)
        {
            Field field = (Field) item;
            result + ", fasm struct = " + field.fasmStructName + ", capacity = " + field.capacity;
        }
        return (result + " }").toString();
    }

    private static String supertypesToString(ClassType type) {
        ClassType supertype = type.getSuperclassType();
        if(supertype == null) return "";
        StringBuilder result = new StringBuilder() + '(' + supertype.specialCanonicalName;
        for(int length = type.getSuperservicesLength(), int index = 0; index < length; index++) result + ", " + type.getSuperserviceTypeAt(index).specialCanonicalName;
        return (result + ')').toString();
    }

    private final Programme fldProgramme;

    public (Object monitor, FileSystem fileSystem, String fileName, Programme programme): super(monitor, fileSystem, fileName) { fldProgramme = programme; }

    public void run() {
        try
        {
            try
            {
                print(fldFileSystem, fldFileName, fldProgramme);
            } catch(IOException exception)
            {
                exception.printStackTrace();
            }
        } finally
        {
            terminate();
        }
    }
}

class AVTCPrintLexemesThread(AVTCPrintThread, Runnable, AVTOOConstants)
{
    private static void print(FileSystem fileSystem, String fileName, Library project) throws IOException {
        if(fileSystem.isObjectExists(fileName)) fileSystem.deleteFile(fileName);
        PrintStream debugOutput = new PrintStream(fileSystem.createFile(fileName));
        try
        {
            StringBuilder debugBuilder = new StringBuilder();
            for(Source[] sources = project.sources.clone(), int slength = sources.length, int sindex = 0; sindex < slength; sindex++)
            {
                TextSource source = (TextSource) sources[sindex];
                debugOutput.println(source.outputPath);
                printLanguageLexemes(source, debugOutput);
            }
        } finally
        {
            debugOutput.close();
        }
    }

    private static void printDocumentLexemes(LexemeSequence sequence, PrintStream printer) {
        for(int length = sequence.length, int position = 0; position < length; position++)
        {
            int2 location = sequence.getLexemeLocation(position) + new byte2 { 1, 1 };
            int kindAsInt = sequence.getLexemeKind(position);
            String kindAsString;
            switch(kindAsInt)
            {
            case D_TEXT          : kindAsString = "D_TEXT          "; break;
            case D_NAME          : kindAsString = "D_NAME          "; break;
            case D_ALINK         : kindAsString = "D_ALINK         "; break;
            case D_APARAM        : kindAsString = "D_APARAM        "; break;
            case D_ARETURN       : kindAsString = "D_ARETURN       "; break;
            case D_ATHROWS       : kindAsString = "D_ATHROWS       "; break;
            case D_ASINCE        : kindAsString = "D_ASINCE        "; break;
            case D_ASEE          : kindAsString = "D_ASEE          "; break;
            case D_SCAL_DIVU     : kindAsString = "D_SCAL_DIVU     "; break;
            case D_SCAL_REMU     : kindAsString = "D_SCAL_REMU     "; break;
            case D_SCAL_SHR      : kindAsString = "D_SCAL_SHR      "; break;
            case D_SCAL_SHRU     : kindAsString = "D_SCAL_SHRU     "; break;
            case D_SCAL_SHL      : kindAsString = "D_SCAL_SHL      "; break;
            case D_SCAL_GE       : kindAsString = "D_SCAL_GE       "; break;
            case D_SCAL_LE       : kindAsString = "D_SCAL_LE       "; break;
            case D_SCAL_EQ       : kindAsString = "D_SCAL_EQ       "; break;
            case D_SCAL_NE       : kindAsString = "D_SCAL_NE       "; break;
            case D_VECT_LUP      : kindAsString = "D_VECT_LUP      "; break;
            case D_VECT_UUP      : kindAsString = "D_VECT_UUP      "; break;
            case D_VECT_PCK      : kindAsString = "D_VECT_PCK      "; break;
            case D_VECT_MUL      : kindAsString = "D_VECT_MUL      "; break;
            case D_VECT_DIV      : kindAsString = "D_VECT_DIV      "; break;
            case D_VECT_ADD      : kindAsString = "D_VECT_ADD      "; break;
            case D_VECT_SUB      : kindAsString = "D_VECT_SUB      "; break;
            case D_VECT_SHR      : kindAsString = "D_VECT_SHR      "; break;
            case D_VECT_SHRU     : kindAsString = "D_VECT_SHRU     "; break;
            case D_VECT_SHL      : kindAsString = "D_VECT_SHL      "; break;
            case D_VECT_GT       : kindAsString = "D_VECT_GT       "; break;
            case D_VECT_GE       : kindAsString = "D_VECT_GE       "; break;
            case D_VECT_LT       : kindAsString = "D_VECT_LT       "; break;
            case D_VECT_LE       : kindAsString = "D_VECT_LE       "; break;
            case D_VECT_EQ       : kindAsString = "D_VECT_EQ       "; break;
            case D_VECT_NE       : kindAsString = "D_VECT_NE       "; break;
            case D_VECT_HMUL     : kindAsString = "D_VECT_HMUL     "; break;
            case D_VECT_HMULU    : kindAsString = "D_VECT_HMULU    "; break;
            case D_VECT_SADD     : kindAsString = "D_VECT_SADD     "; break;
            case D_VECT_SADDU    : kindAsString = "D_VECT_SADDU    "; break;
            case D_VECT_SSUB     : kindAsString = "D_VECT_SSUB     "; break;
            case D_VECT_SSUBU    : kindAsString = "D_VECT_SSUBU    "; break;
            case D_PARENTH_OPENED: kindAsString = "D_PARENTH_OPENED"; break;
            case D_PARENTH_CLOSED: kindAsString = "D_PARENTH_CLOSED"; break;
            case D_BRACKET_OPENED: kindAsString = "D_BRACKET_OPENED"; break;
            case D_BRACKET_CLOSED: kindAsString = "D_BRACKET_CLOSED"; break;
            case D_CURLY_OPENED  : kindAsString = "D_CURLY_OPENED  "; break;
            case D_CURLY_CLOSED  : kindAsString = "D_CURLY_CLOSED  "; break;
            case D_TAG_OPENED    : kindAsString = "D_TAG_OPENED    "; break;
            case D_TAG_CLOSED    : kindAsString = "D_TAG_CLOSED    "; break;
            case D_EQUALS        : kindAsString = "D_EQUALS        "; break;
            case D_PERIOD        : kindAsString = "D_PERIOD        "; break;
            case D_COMMA         : kindAsString = "D_COMMA         "; break;
            case D_EXCLAM_MARK   : kindAsString = "D_EXCLAM_MARK   "; break;
            case D_VERTICAL_LINE : kindAsString = "D_VERTICAL_LINE "; break;
            case D_AMPERSAND     : kindAsString = "D_AMPERSAND     "; break;
            case D_TILDE         : kindAsString = "D_TILDE         "; break;
            case D_POUND_SIGN    : kindAsString = "D_POUND_SIGN    "; break;
            case D_CIRCUMFLEX_ACC: kindAsString = "D_CIRCUMFLEX_ACC"; break;
            case D_ASTERISK      : kindAsString = "D_ASTERISK      "; break;
            case D_SOLIDUS       : kindAsString = "D_SOLIDUS       "; break;
            case D_PERCENT       : kindAsString = "D_PERCENT       "; break;
            case D_PLUS          : kindAsString = "D_PLUS          "; break;
            case D_MINUS         : kindAsString = "D_MINUS         "; break;
            case D_AT            : kindAsString = "D_AT            "; break;
            case D_EOL           : kindAsString = "D_EOL           "; break;
            case D_EOP           : kindAsString = "D_EOP           "; break;
            case D_END           : kindAsString = "D_END           "; break;
            default              : kindAsString = "<unknown>       ";
            }
            if(sequence.getLexemeType(position) != LT_STRING)
            {
                printer.printlnf(
                    "\t\t[%0:5%] %1:4%:%2:3% %3%",
                    new Object[] { Int.toString(position), Int.toString(location[0]), Int.toString(location[1]), kindAsString }
                );
            } else
            {
                printer.printlnf(
                    "\t\t[%0:5%] %1:4%:%2:3% %3% (\u0022%4%\u0022)",
                    new Object[] { Int.toString(position), Int.toString(location[0]), Int.toString(location[1]), kindAsString, sequence.getLexemeString(position) }
                );
            }
        }
    }

    private static void printLanguageLexemes(LexemeSequence sequence, PrintStream printer) {
        for(int length = sequence.length, int position = 0; position < length; position++)
        {
            int2 location = sequence.getLexemeLocation(position) + new byte2 { 1, 1 };
            int kindAsInt = sequence.getLexemeKind(position);
            String kindAsString;
            switch(kindAsInt)
            {
            case PRIVATE       : kindAsString = "PRIVATE       "; break;
            case PACKAGE       : kindAsString = "PACKAGE       "; break;
            case PROTECTED     : kindAsString = "PROTECTED     "; break;
            case PUBLIC        : kindAsString = "PUBLIC        "; break;
            case PUBLISHED     : kindAsString = "PUBLISHED     "; break;
            case IMPORT        : kindAsString = "IMPORT        "; break;
            case UNION         : kindAsString = "UNION         "; break;
            case ABSTRACT      : kindAsString = "ABSTRACT      "; break;
            case FINAL         : kindAsString = "FINAL         "; break;
            case CLASS         : kindAsString = "CLASS         "; break;
            case STRUCT        : kindAsString = "STRUCT        "; break;
            case SERVICE       : kindAsString = "SERVICE       "; break;
            case INTERFACE     : kindAsString = "INTERFACE     "; break;
            case HELPER        : kindAsString = "HELPER        "; break;
            case STATIC        : kindAsString = "STATIC        "; break;
            case NATIVE        : kindAsString = "NATIVE        "; break;
            case INTERRUPT     : kindAsString = "INTERRUPT     "; break;
            case SYNCHRONIZED  : kindAsString = "SYNCHRONIZED  "; break;
            case OPERATOR      : kindAsString = "OPERATOR      "; break;
            case THROWS        : kindAsString = "THROWS        "; break;
            case FALSE         : kindAsString = "FALSE         "; break;
            case TRUE          : kindAsString = "TRUE          "; break;
            case NULL          : kindAsString = "NULL          "; break;
            case NEW           : kindAsString = "NEW           "; break;
            case SUPER         : kindAsString = "SUPER         "; break;
            case THIS          : kindAsString = "THIS          "; break;
            case INSTANCEOF    : kindAsString = "INSTANCEOF    "; break;
            case VOID          : kindAsString = "VOID          "; break;
            case BOOLEAN       : kindAsString = "BOOLEAN       "; break;
            case CHAR          : kindAsString = "CHAR          "; break;
            case REAL          : kindAsString = "REAL          "; break;
            case DOUBLE        : kindAsString = "DOUBLE        "; break;
            case DOUBLE2       : kindAsString = "DOUBLE2       "; break;
            case DOUBLE4       : kindAsString = "DOUBLE4       "; break;
            case DOUBLE8       : kindAsString = "DOUBLE8       "; break;
            case FLOAT         : kindAsString = "FLOAT         "; break;
            case FLOAT2        : kindAsString = "FLOAT2        "; break;
            case FLOAT4        : kindAsString = "FLOAT4        "; break;
            case FLOAT8        : kindAsString = "FLOAT8        "; break;
            case BYTE          : kindAsString = "BYTE          "; break;
            case BYTE2         : kindAsString = "BYTE2         "; break;
            case BYTE4         : kindAsString = "BYTE4         "; break;
            case BYTE8         : kindAsString = "BYTE8         "; break;
            case SHORT         : kindAsString = "SHORT         "; break;
            case SHORT2        : kindAsString = "SHORT2        "; break;
            case SHORT4        : kindAsString = "SHORT4        "; break;
            case SHORT8        : kindAsString = "SHORT8        "; break;
            case INT           : kindAsString = "INT           "; break;
            case INT2          : kindAsString = "INT2          "; break;
            case INT4          : kindAsString = "INT4          "; break;
            case INT8          : kindAsString = "INT8          "; break;
            case LONG          : kindAsString = "LONG          "; break;
            case LONG2         : kindAsString = "LONG2         "; break;
            case LONG4         : kindAsString = "LONG4         "; break;
            case LONG8         : kindAsString = "LONG8         "; break;
            case WITH          : kindAsString = "WITH          "; break;
            case IF            : kindAsString = "IF            "; break;
            case ELSE          : kindAsString = "ELSE          "; break;
            case SWITCH        : kindAsString = "SWITCH        "; break;
            case CASE          : kindAsString = "CASE          "; break;
            case DEFAULT       : kindAsString = "DEFAULT       "; break;
            case DO            : kindAsString = "DO            "; break;
            case FOR           : kindAsString = "FOR           "; break;
            case WHILE         : kindAsString = "WHILE         "; break;
            case BREAK         : kindAsString = "BREAK         "; break;
            case CONTINUE      : kindAsString = "CONTINUE      "; break;
            case RETURN        : kindAsString = "RETURN        "; break;
            case THROW         : kindAsString = "THROW         "; break;
            case TRY           : kindAsString = "TRY           "; break;
            case CATCH         : kindAsString = "CATCH         "; break;
            case FINALLY       : kindAsString = "FINALLY       "; break;
            case INC_LOCAL     : kindAsString = "INC_LOCAL     "; break;
            case DEC_LOCAL     : kindAsString = "DEC_LOCAL     "; break;
            case BOOL_NOT      : kindAsString = "BOOL_NOT      "; break;
            case BOOL_AND      : kindAsString = "BOOL_AND      "; break;
            case BOOL_OR       : kindAsString = "BOOL_OR       "; break;
            case O_BIT_NOT     : kindAsString = "O_BIT_NOT     "; break;
            case O_BIT_AND     : kindAsString = "O_BIT_AND     "; break;
            case O_BIT_OR      : kindAsString = "O_BIT_OR      "; break;
            case O_BIT_XOR     : kindAsString = "O_BIT_XOR     "; break;
            case O_SCAL_MUL    : kindAsString = "O_SCAL_MUL    "; break;
            case O_SCAL_DIV    : kindAsString = "O_SCAL_DIV    "; break;
            case O_SCAL_DIVU   : kindAsString = "O_SCAL_DIVU   "; break;
            case O_SCAL_REM    : kindAsString = "O_SCAL_REM    "; break;
            case O_SCAL_REMU   : kindAsString = "O_SCAL_REMU   "; break;
            case O_SCAL_ADD    : kindAsString = "O_SCAL_ADD    "; break;
            case O_SCAL_SUB    : kindAsString = "O_SCAL_SUB    "; break;
            case O_SCAL_SHR    : kindAsString = "O_SCAL_SHR    "; break;
            case O_SCAL_SHRU   : kindAsString = "O_SCAL_SHRU   "; break;
            case O_SCAL_SHL    : kindAsString = "O_SCAL_SHL    "; break;
            case O_SCAL_GT     : kindAsString = "O_SCAL_GT     "; break;
            case O_SCAL_GE     : kindAsString = "O_SCAL_GE     "; break;
            case O_SCAL_LT     : kindAsString = "O_SCAL_LT     "; break;
            case O_SCAL_LE     : kindAsString = "O_SCAL_LE     "; break;
            case O_SCAL_EQ     : kindAsString = "O_SCAL_EQ     "; break;
            case O_SCAL_NE     : kindAsString = "O_SCAL_NE     "; break;
            case O_VECT_LUP    : kindAsString = "O_VECT_LUP    "; break;
            case O_VECT_UUP    : kindAsString = "O_VECT_UUP    "; break;
            case O_VECT_PCK    : kindAsString = "O_VECT_PCK    "; break;
            case O_VECT_MUL    : kindAsString = "O_VECT_MUL    "; break;
            case O_VECT_DIV    : kindAsString = "O_VECT_DIV    "; break;
            case O_VECT_ADD    : kindAsString = "O_VECT_ADD    "; break;
            case O_VECT_SUB    : kindAsString = "O_VECT_SUB    "; break;
            case O_VECT_SHR    : kindAsString = "O_VECT_SHR    "; break;
            case O_VECT_SHRU   : kindAsString = "O_VECT_SHRU   "; break;
            case O_VECT_SHL    : kindAsString = "O_VECT_SHL    "; break;
            case O_VECT_GT     : kindAsString = "O_VECT_GT     "; break;
            case O_VECT_GE     : kindAsString = "O_VECT_GE     "; break;
            case O_VECT_LT     : kindAsString = "O_VECT_LT     "; break;
            case O_VECT_LE     : kindAsString = "O_VECT_LE     "; break;
            case O_VECT_EQ     : kindAsString = "O_VECT_EQ     "; break;
            case O_VECT_NE     : kindAsString = "O_VECT_NE     "; break;
            case O_VECT_HMUL   : kindAsString = "O_VECT_HMUL   "; break;
            case O_VECT_HMULU  : kindAsString = "O_VECT_HMULU  "; break;
            case O_VECT_SADD   : kindAsString = "O_VECT_SADD   "; break;
            case O_VECT_SADDU  : kindAsString = "O_VECT_SADDU  "; break;
            case O_VECT_SSUB   : kindAsString = "O_VECT_SSUB   "; break;
            case O_VECT_SSUBU  : kindAsString = "O_VECT_SSUBU  "; break;
            case A_BIT_AND     : kindAsString = "A_BIT_AND     "; break;
            case A_BIT_OR      : kindAsString = "A_BIT_OR      "; break;
            case A_BIT_XOR     : kindAsString = "A_BIT_XOR     "; break;
            case A_SCAL_MUL    : kindAsString = "A_SCAL_MUL    "; break;
            case A_SCAL_DIV    : kindAsString = "A_SCAL_DIV    "; break;
            case A_SCAL_DIVU   : kindAsString = "A_SCAL_DIVU   "; break;
            case A_SCAL_REM    : kindAsString = "A_SCAL_REM    "; break;
            case A_SCAL_REMU   : kindAsString = "A_SCAL_REMU   "; break;
            case A_SCAL_ADD    : kindAsString = "A_SCAL_ADD    "; break;
            case A_SCAL_SUB    : kindAsString = "A_SCAL_SUB    "; break;
            case A_SCAL_SHR    : kindAsString = "A_SCAL_SHR    "; break;
            case A_SCAL_SHRU   : kindAsString = "A_SCAL_SHRU   "; break;
            case A_SCAL_SHL    : kindAsString = "A_SCAL_SHL    "; break;
            case A_VECT_MUL    : kindAsString = "A_VECT_MUL    "; break;
            case A_VECT_DIV    : kindAsString = "A_VECT_DIV    "; break;
            case A_VECT_ADD    : kindAsString = "A_VECT_ADD    "; break;
            case A_VECT_SUB    : kindAsString = "A_VECT_SUB    "; break;
            case A_VECT_SHR    : kindAsString = "A_VECT_SHR    "; break;
            case A_VECT_SHRU   : kindAsString = "A_VECT_SHRU   "; break;
            case A_VECT_SHL    : kindAsString = "A_VECT_SHL    "; break;
            case A_VECT_GT     : kindAsString = "A_VECT_GT     "; break;
            case A_VECT_GE     : kindAsString = "A_VECT_GE     "; break;
            case A_VECT_LT     : kindAsString = "A_VECT_LT     "; break;
            case A_VECT_LE     : kindAsString = "A_VECT_LE     "; break;
            case A_VECT_EQ     : kindAsString = "A_VECT_EQ     "; break;
            case A_VECT_NE     : kindAsString = "A_VECT_NE     "; break;
            case A_VECT_HMUL   : kindAsString = "A_VECT_HMUL   "; break;
            case A_VECT_HMULU  : kindAsString = "A_VECT_HMULU  "; break;
            case A_VECT_SADD   : kindAsString = "A_VECT_SADD   "; break;
            case A_VECT_SADDU  : kindAsString = "A_VECT_SADDU  "; break;
            case A_VECT_SSUB   : kindAsString = "A_VECT_SSUB   "; break;
            case A_VECT_SSUBU  : kindAsString = "A_VECT_SSUBU  "; break;
            case PARENTH_OPENED: kindAsString = "PARENTH_OPENED"; break;
            case PARENTH_CLOSED: kindAsString = "PARENTH_CLOSED"; break;
            case BRACKET_OPENED: kindAsString = "BRACKET_OPENED"; break;
            case BRACKET_CLOSED: kindAsString = "BRACKET_CLOSED"; break;
            case CURLY_OPENED  : kindAsString = "CURLY_OPENED  "; break;
            case CURLY_CLOSED  : kindAsString = "CURLY_CLOSED  "; break;
            case EQUALS        : kindAsString = "EQUALS        "; break;
            case QUESTION      : kindAsString = "QUESTION      "; break;
            case REVERSE       : kindAsString = "REVERSE       "; break;
            case PERIOD        : kindAsString = "PERIOD        "; break;
            case COMMA         : kindAsString = "COMMA         "; break;
            case COLON         : kindAsString = "COLON         "; break;
            case SEMICOLON     : kindAsString = "SEMICOLON     "; break;
            case L_NAME        : kindAsString = "L_NAME        "; break;
            case L_STRING      : kindAsString = "L_STRING      "; break;
            case L_DOC         : kindAsString = "L_DOC         "; break;
            case L_BOOLEAN     : kindAsString = "L_BOOLEAN     "; break;
            case L_CHAR        : kindAsString = "L_CHAR        "; break;
            case L_REAL        : kindAsString = "L_REAL        "; break;
            case L_DOUBLE      : kindAsString = "L_DOUBLE      "; break;
            case L_FLOAT       : kindAsString = "L_FLOAT       "; break;
            case L_BYTE        : kindAsString = "L_BYTE        "; break;
            case L_SHORT       : kindAsString = "L_SHORT       "; break;
            case L_INT         : kindAsString = "L_INT         "; break;
            case L_LONG        : kindAsString = "L_LONG        "; break;
            case L_END         : kindAsString = "L_END         "; break;
            default            : kindAsString = "<unknown>     ";
            }
            switch(sequence.getLexemeType(position))
            {
            case LT_BOOLEAN:
                printer.printlnf(
                    "\t[%0:5%] %1:4%:%2:3% %3% %4%",
                    new Object[] { Int.toString(position), Int.toString(location[0]), Int.toString(location[1]), kindAsString, String.valueOf(sequence.getLexemeBoolean(position)) }
                );
                break;
            case LT_CHAR:
                printer.printlnf(
                    "\t[%0:5%] %1:4%:%2:3% %3% \'%4%\'",
                    new Object[] { Int.toString(position), Int.toString(location[0]), Int.toString(location[1]), kindAsString, String.valueOf(sequence.getLexemeChar(position)) }
                );
                break;
            case LT_BYTE:
            case LT_SHORT:
            case LT_INT:
                printer.printlnf(
                    "\t[%0:5%] %1:4%:%2:3% %3% %4%",
                    new Object[] { Int.toString(position), Int.toString(location[0]), Int.toString(location[1]), kindAsString, String.valueOf(sequence.getLexemeInt(position)) }
                );
                break;
            case LT_LONG:
                printer.printlnf(
                    "\t[%0:5%] %1:4%:%2:3% %3% %4%",
                    new Object[] { Int.toString(position), Int.toString(location[0]), Int.toString(location[1]), kindAsString, String.valueOf(sequence.getLexemeLong(position)) }
                );
                break;
            case LT_FLOAT:
                printer.printlnf(
                    "\t[%0:5%] %1:4%:%2:3% %3% %4%",
                    new Object[] { Int.toString(position), Int.toString(location[0]), Int.toString(location[1]), kindAsString, String.valueOf(sequence.getLexemeFloat(position)) }
                );
                break;
            case LT_DOUBLE:
                printer.printlnf(
                    "\t[%0:5%] %1:4%:%2:3% %3% %4%",
                    new Object[] { Int.toString(position), Int.toString(location[0]), Int.toString(location[1]), kindAsString, String.valueOf(sequence.getLexemeDouble(position)) }
                );
                break;
            case LT_REAL:
                printer.printlnf(
                    "\t[%0:5%] %1:4%:%2:3% %3% %4%",
                    new Object[] { Int.toString(position), Int.toString(location[0]), Int.toString(location[1]), kindAsString, String.valueOf(sequence.getLexemeReal(position)) }
                );
                break;
            case LT_STRING:
                printer.printlnf(
                    "\t[%0:5%] %1:4%:%2:3% %3% \u0022%4%\u0022",
                    new Object[] { Int.toString(position), Int.toString(location[0]), Int.toString(location[1]), kindAsString, String.valueOf(sequence.getLexemeString(position)) }
                );
                break;
            default:
                printer.printlnf(
                    "\t[%0:5%] %1:4%:%2:3% %3%",
                    new Object[] { Int.toString(position), Int.toString(location[0]), Int.toString(location[1]), kindAsString }
                );
                Object component = sequence[position];
                if(component instanceof LexemeSequence) printDocumentLexemes((LexemeSequence) component, printer);
            }
        }
    }

    private final Library fldProject;

    public (Object monitor, FileSystem fileSystem, String fileName, Library project): super(monitor, fileSystem, fileName) { fldProject = project; }

    public void run() {
        try
        {
            try
            {
                print(fldFileSystem, fldFileName, fldProject);
            } catch(IOException exception)
            {
                exception.printStackTrace();
            }
        } finally
        {
            terminate();
        }
    }
}