Spracovanie deklarácie triedy JMM

Ciele
  1. Pochopiť štruktúru súborov JAL.
  2. Pochopiť spôsob ukladania informácii o prvkoch programu (triedach, metódach, dátových členoch).
  3. Pochopiť princíp vytvárania prekladu.
Úvod
    Na tomto cvičení je predstavený ďalší krok vo vývoji prekladača jazyka JMM. Definícia gramatiky je doplnená akciami, ktoré zabezpečia zozbieranie informácií o základných prvkoch programu a vygenerovanie kostry výstupného textu.
Postup
  1. Výsledkom prekladu súborov programov v jazyku JMM je súbor s príponou .jal, ktorý obsahuje textovú formu Java class súborov v jazyku Jasmin. Táto textová forma je potom nástrojom Jasmin preložená do binárnej formy (bytecode). Pre každú triedu musí byť vygenerovaný zodpovedajúcu jal súbor. Tento súbor začína informáciami o triede v nasledovnom tvare:

    
    .source <zdrojový-súbor>
    .class  <modifikátor-prístupu> <meno-triedy>
    .super  <meno-nadtriedy>
    

    Za tým nasledujú definície dátových členov a metód triedy:

    
    .field <modifikátor-prístupu> <meno-dátového-člena> <signatúra>
    
    .method <modifikátor-prístupu> <meno-metódy><signatúra>
        <inštrukcie>
    .end method
    

    Typy metód, dátových členov a premenných sú označené pomocou signatúr – skráteného vyjadrenia typov. Syntax signatúr je vysvetlená v tabuľkách.

    Tab.: Syntax signatúry
    signatúra-metódy ( typ-parametrov ) typ-návratovej-hodnoty
    signatúra-dátového-člena typ-člena
    typ-člena základný-typ | typ-objektu | typ-poľa
    základný-typ B | C | D | F | I | J | S | Z
    typ-objektu L úplné-meno-triedy ;
    typ-poľa [ typ_člena
    typ-návratovej-hodnoty typ-člena | V
    typ-parametrov typ-člena ... typ-člena
    Tab.: Signatúry základných typov
    Signatúra Typ
    B byte
    C char
    D double
    F float
    I int
    J long
    S short
    Z boolean
    Tab.: Príklady signatúr
    Metóda alebo dátový člen Signatúra
    void main(String[] args) ([Ljava/lang/String;)V
    boolean action(Event evt, Object arg) (Ljava/awt/Event;Ljava/lang/Object;)Z
    int xx I
  2. Všetky informácie o pomenovaných prvkoch prekladaného jazyka, ktoré sú potrebné pre preklad, sa v procese prekladu ukladajú do tzv. tabuľky symbolov. Tabuľka symbolov môže byť implementovaná ako jedna údajová štruktúra pre všetky druhy pomenovaných prvkov prekladaného jazyka, alebo môže byť rozdelená do viacerých tabuliek zvlášť pre každý druh pomenovaného prvku. Pri preklade programu v jazyku JMM je potrebné uložiť všetky informácie o triedach, ich dátových členoch a metódach. Tieto informácie budú potrebné pre generovanie výstupného kódu, ale aj pre spracovanie ostatných častí programu, kde sú tieto dátové členy a metódy používané. Informácie o triedach definovaných v programe sú uložené v tabuľke tried, ktorá je definovaná následovne:

    
    struct {
    	char *menoTr;     /* Meno triedy uvedene v kode */
    	char *javaTr;     /* Uplne meno triedy pre JVM */
    	char *sigTr;      /* Signatura triedy */
    	char *menoNadTr;  /* Meno nadtriedy */
    	int ixntr;        /* Index na nadtriedu v tabulke tried */
    	uint pristup;     /* Modifikatory pristupu */
    	int pocDatClenov; /* Pocet datovych clenov */
    	dclen* DatCleny;  /* Pole informacii o datovych clenoch */
    	int pocMetod;     /* Pocet metod */
    	met* Metody;      /* Pole informacii o metodach */
    } triedy[20];
    
    int ix_t; /* Index aktualne spracovavanej triedy */
    

    Pre každú triedu je tiež vytvorená tabuľka dátových členov a tabuľka metód, ktorých štruktúra je nasledovná:

    
    /* Datovy clen */
    typedef struct {
    	uint pristup; /* Modifikatory pristupu */
    	char *meno;
    	char *signatura;
    } dclen;
    
    /* Metoda */
    typedef struct {
    	uint pristup;     /* Modifikatory pristupu */
    	char *meno;
    	char *signaturaP; /* Signatura parametrov */
    	char *signaturaR; /* Signatura navratovej hodnoty */
    	int velkostLP;    /* Velkost pamate pre lokalne premenne */
    	char *kod;        /* Kod metody */
    } met;
    

    Modifikátory, určujúce viditeľnosť prvkov programu (private, protected, public) a ďalšie ich vlastnosti (static, final, abstract) sú uložené ako jednotlivé bity v jednej premennej typu unsigned int. Každému modifikátoru je pridelená jedna pozícia v dvojkovej reprezentácií čísla a hodnota 1 na tejto pozícii znamená prítomnosť daného modifikátora. Pre manipuláciu s takto uloženými modifikátormi sú definované konštanty zodpovedajúce hodnote 1 na potrebnej pozícii:

    
    #define MOD_PUBLIC    0x0001
    #define MOD_PRIVATE   0x0002
    #define MOD_PROTECTED 0x0004
    #define MOD_STATIC    0x0008
    #define MOD_FINAL     0x0010
    #define MOD_NATIVE    0x0100
    #define MOD_ABSTRACT  0x0400
    
    Poznámka: Modifikátor native označuje externé triedy, teda triedy, ktoré nie sú definované v danom JMM programe, ale sú súčasťou Java knižníc.
    Úloha: V zdrojových kódoch prekladača sa oboznámte sa so štruktúrami pre uchovanie informácii o triedach, s funkciami pre prácu s nimi a s ich použitím v prekladači.
  3. Počas syntaktickej analýzy programu sa postupne napĺňa tabuľka tried a zhromažďujú sa informácie o všetkých definovaných dátových členoch a metódach. Kód metód sa pritom prekladá do podoby JVM inštrukcii. Nakoniec je pre každú triedu, definovanú v programe vytvorený výstupný JAL súbor obsahujúci inštrukcie metód a všetky informácie o štruktúre triedy.

    Keďže program môže používať niektoré štandardné triedy jazyka Java, informácie o týchto triedach je potrebné tiež uložiť do tabuľky tried. Tieto informácie sú uložené v textovej podobe v súbore java.api (hierarchia tried) a na ich načítanie slúži funkcia ulozImp. Táto funkcia je používaná pre spracovanie deklarácie import a tiež pre načítanie niekoľkých základných tried ešte pred spustením syntaktickej analýzy vo funkcii main.

    Úloha: Doplňte výstup zdedených dátových členov a metód (do funkcie vypisTriedy) v tvare:
    • pre zdedené dátové členy:
      .inheritedfield <modifikátory-prístupu> <meno> <signatúra-typu>
    • pre zdedené metódy:
      .inheritedmethod <modifikátory-prístupu> <meno> <signatúra-metódy>
    Poznámka: Takéto klauzuly nie sú platnými v jazyku Jasmin a ich výpis slúži len na ukážku práce s údajovými štruktúrami obsahujúcimi informácie o triedach.
Zdroje
  1. Zdrojové kódy pre cvičenie 4
  2. Inštrukcie JVM
  3. Dokumentácia nástroja Jasmin
Doplňujúce úlohy
    Príklad: Doplňte do prekladača podporu pre implementáciu rozhraní. Zabezpečte, aby pri použití klauzuly implements v definícii triedy, bola pre každé implementované rozhranie vygenerovaná do výstupného JAL súboru direktíva v tvare:
    .implements <meno-rozhrania>
    Poznámka: Pre uchovanie informácií o implementovaných rozhraniach potrebujete pridať novú položku do tabuľky tried a doplniť akcie k pravidlu ImpRozhrania, ktorá tieto uchová index implementovaného rozhrania v tabuľke tried.
comments powered by Disqus