!package.avt

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

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

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

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

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

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

package ru.malik.elaborarer.avtoo.avtc;

import avt.io.*;
import platform.independent.filesystem.*;
import platform.independent.osservices.*;
import ru.malik.elaborarer.avtoo.lang.*;

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

    public (Object monitor, FileSystem fileSystem, String fileName) {
        try
        {
            fldMonitor = monitor;
            fldFileName = fileName != null ? fileName : "";
            fldFileSystem = fileSystem != null ? fileSystem : FileSystemRoot.get(Process.current().workingDirectory).fileSystem;
        } catch(IOException exception)
        {
            exception.printStackTrace();
        }
    }

    public boolean isTerminated() { return fldTerminated; }

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

package class PrintCodeThread(PrintThread, 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.append("\t").append(attributesToString(pack)).append(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.append("\t\t").append(attributesToString(type)).append(namesToString(type)));
                        } else
                        {
                            debugOutput.println(debugBuilder.append("\t\t").append(attributesToString(type)).append(supertypesToString((ClassType) type)).append(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.append("\t\t\t").append(attributesToString(member));
                            if(member instanceof Callable) with((Callable) member)
                            {
                                debugBuilder.append(arguments.toFullString());
                                if(member instanceof Method) with((Method) member) for(int elength = getThrowablesLength(), int eindex = 0; eindex < elength; eindex++)
                                {
                                    debugBuilder.append(eindex < 1 ? " throws " : ", ").append(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.append(" = ").append(value);
                            } else if(member instanceof Property) with((Property) member)
                            {
                                Method index = indexSynthetic;
                                Method read = readSynthetic;
                                Method write = writeSynthetic;
                                Method stored = storedSynthetic;
                                debugBuilder.append(" { ");
                                if(index != null)
                                {
                                    Member pmember = indexMember;
                                    Constant constant = indexConstant;
                                    debugBuilder.append("index = ").append(pmember != null ? pmember.specialSimpleName : constant == null ? index.specialSimpleName : constant.toString()).append(", ");
                                }
                                if(read == null)
                                {
                                    Member pmember = writeMember;
                                    debugBuilder.append("write = ").append(pmember != null ? pmember.specialSimpleName : write.specialSimpleName);
                                } else if(write == null)
                                {
                                    Member pmember = readMember;
                                    Constant constant = readConstant;
                                    debugBuilder.append("read = ").append(pmember != null ? pmember.specialSimpleName : constant == null ? read.specialSimpleName : constant.toString());
                                } else
                                {
                                    Member pmember = readMember;
                                    Constant constant = readConstant;
                                    debugBuilder.append("read = ").append(pmember != null ? pmember.specialSimpleName : constant == null ? read.specialSimpleName : constant.toString()).append(", ");
                                    pmember = writeMember;
                                    debugBuilder.append("write = ").append(pmember != null ? pmember.specialSimpleName : write.specialSimpleName);
                                }
                                if(stored != null)
                                {
                                    Member pmember = storedMember;
                                    Constant constant = storedConstant;
                                    debugBuilder.append(", stored = ").append(pmember != null ? pmember.specialSimpleName : constant == null ? stored.specialSimpleName : constant.toString());
                                }
                                debugBuilder.append(" }");
                            }
                            debugOutput.println(debugBuilder.append(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.append('\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.append("0x").append(Long.toHexString(System.identityHashCode(node)));
                                if(order >= 0)
                                {
                                    int debug = node.debugIndex;
                                    int label = node.labelIndex;
                                    debugBuilder.append('(').append(order);
                                    if(debug >= 0)
                                    {
                                        debugBuilder.append(", D.").append(debug);
                                    } else if(label >= 0)
                                    {
                                        debugBuilder.append(", L.").append(label);
                                    }
                                    debugBuilder.append(')');
                                }
                                debugBuilder.appendf("[%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.append('(');
                                        if((instruction == DECLARE_LOCAL || instruction == DECLARE_WITH) && operand instanceof TypedItem)
                                        {
                                            debugBuilder.append(((TypedItem) operand).type).append(' ');
                                        }
                                        debugBuilder.append(operand);
                                        if((operand = node.operand2) != null)
                                        {
                                            debugBuilder.append(", ").append(operand);
                                        }
                                        debugBuilder.append(')');
                                        break label1;
                                    }
                                    Object reference = node.reference1;
                                    if(reference != null)
                                    {
                                        debugBuilder.append('(').append(!(reference instanceof Node) ? reference.toString() : "0x" + Long.toHexString(System.identityHashCode(reference)));
                                        if((reference = node.reference2) != null)
                                        {
                                            debugBuilder.append(", ").append(!(reference instanceof Node) ? reference.toString() : "0x" + Long.toHexString(System.identityHashCode(reference)));
                                        }
                                        debugBuilder.append(')');
                                    }
                                }
                                int ordert;
                                int jlength = node.getJumpCasesLength();
                                if(jlength > 0 || instruction == JUMP || instruction == RETURN)
                                {
                                    Node target = node.jumpDefault;
                                    debugBuilder.append("[default").append(target == null ? ">null" : ">0x" + Long.toHexString(System.identityHashCode(target)));
                                    for(int jindex = 0; jindex < jlength; jindex++)
                                    {
                                        target = node.getJumpCaseNodeAt(jindex);
                                        debugBuilder.append(", ").append(Int.toString(node.getJumpCaseValueAt(jindex))).
                                            append(target == null ? ">null" : ">0x" + Long.toHexString(System.identityHashCode(target)))
                                        ;
                                    }
                                    debugBuilder.append("]");
                                }
                                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.append("private ");
                break;
            }
            case RESERVED_PACKAGE:
            case PACKAGE:
            {
                attributesAsString.append("package ");
                break;
            }
            case PROTECTED:
            {
                attributesAsString.append("protected ");
                break;
            }
            case PUBLIC:
            {
                attributesAsString.append("public ");
                break;
            }
            case PUBLISHED:
            {
                attributesAsString.append("published ");
            }
        }
        if((attributesAsNumber & ATTR_SYNTHETIC) != 0)
        {
            attributesAsString.append("synthetic ");
        }
        if((attributesAsNumber & ATTR_ABSTRACT) != 0)
        {
            attributesAsString.append("abstract ");
        }
        if((attributesAsNumber & ATTR_STATIC) != 0)
        {
            attributesAsString.append("static ");
        }
        if((attributesAsNumber & ATTR_FINAL) != 0)
        {
            attributesAsString.append("final ");
        }
        if(item instanceof Package)
        {
            attributesAsString.append("package ");
        } else if(item instanceof Type) switch((attributesAsNumber & MASK_TYPE) >> 5)
        {
            case ATTR_PRIMITIVE >> 5:
            {
                attributesAsString.append("primitive ");
                break;
            }
            case ATTR_SERVICE >> 5:
            {
                attributesAsString.append("service ");
                break;
            }
            case ATTR_STRUCT >> 5:
            {
                attributesAsString.append("struct ");
                break;
            }
            case ATTR_INTERFACE >> 5:
            {
                attributesAsString.append("interface ");
                break;
            }
            default:
            {
                attributesAsString.append("class ");
            }
        }
        if((attributesAsNumber & ATTR_NATIVE) != 0)
        {
            attributesAsString.append("native ");
        }
        if((attributesAsNumber & ATTR_INTERRUPT) != 0)
        {
            attributesAsString.append("interrupt ");
        }
        if((attributesAsNumber & ATTR_SYNCHRONIZED) != 0)
        {
            attributesAsString.append("synchronized ");
        }
        if(item instanceof TypedItem)
        {
            attributesAsString.append(((TypedItem) item).type.specialCanonicalName).append(' ');
        }
        return attributesAsString.append(item.specialSimpleName).toString();
    }

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

    private static String supertypesToString(ClassType type) {
        ClassType supertype = type.getSuperclassType();
        if(supertype == null) return "";
        StringBuilder result = (new StringBuilder()).append('(').append(supertype.specialCanonicalName);
        for(int length = type.getSuperservicesLength(), int index = 0; index < length; index++) result.append(", ").append(type.getSuperserviceTypeAt(index).specialCanonicalName);
        return result.append(')').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();
        }
    }
}

package class PrintLexemesThread(PrintThread, 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
        {
            for(Source[] sources = project.sources.clone(), int slength = sources.length, int sindex = 0; sindex < slength; sindex++)
            {
                TextSource source = (TextSource) sources[sindex];
                debugOutput.println(source.textSourcePath);
                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();
        }
    }
}