MXML компілятор

Ще одна копія хабора

Головне меню

Навігація за записами

MXML компілятор. Частина 3. Розбираємось у роботі Flex-компілятора

Як завжди всіх, хто не втомився дочитавши до цього рядка - прошу під кат! По-перше, вважаю доречним навести посилання на інші статті з циклу:

По-друге, мені довелося досить добре погуглить щоб знайти актуальне (у зв'язку з передачею Flex-а апачам) посилання на код гілки 4.6, і щоб заощадити Ваш час я просто залишу її тут: opensource.adobe.com/svn //opensource/flex/sdk/branches/4.y/

Компілятори мов

Взагалі Flex компілятор підтримує різні мови програмування. Компілюються вони набором специфічних кожної мови компіляторами. Якщо ви побачите список класів проекту з ім'ям Compiler, можна побачити деякі з них:

компілятор
При цьому не можна стверджувати, що всі мови можуть бути скомпільовані в один етап. Наприклад, компілятор MXML може використовувати залежність, написані на AS3. Тому перш ніж скомпілювати MXML компонент в байткод, компілятор повинен виявити, які AS3 класи йому потрібні і перевірити, що код, що викликається з MXML, на AS3 коректний.

Так само розумно припускати, що різним компіляторам потрібна різна кількість етапів. Наприклад, MXML компілятор вимагає вдвічі більше кроків ніж AS3.

flex2.compiler.SubCompiler

У Flex, всі компілятори мов реалізують той самий інтерфейс -flex2.compiler.SubCompiler:

З методів, що не належать до процесу компіляції, можна виділити:String getName()— як можна зрозуміти з назви, метод повертає ім'я компілятора;isSupportedтаgetSupportedMimeTypes— служать для визначення типу файлів, якіцей компілятор може обертати; benchmarks методи, що відносяться до вимірювання продуктивності компіляції.

Етапи компіляції

Як Ви помітили, процес компіляції складається з 9 етапів. Головний Flex-компілятор виступає в ролі координатора і відповідає за виклик екземплярів компіляторів, які очікують приблизно такого порядку:

  1. preprocess (один раз)
  2. parse1 (один раз)
  3. parse2 (один раз)
  4. analyze1 (один раз)
  5. analyze2 (один раз)
  6. analyze3 (один раз)
  7. analyze4 (один раз)
  8. generate (один раз)
  9. postprocess (багаторазово, доки екземпляр не вимагатиме зупинки)

Крім виклику цих методів, головний Flex-компілятор робить низку речей:

  • Підбирає відповідний екземпляр компілятора, ґрунтуючись на типі вихідного файлу;
  • Отримує від екземплярів список не дозволених типів та шукає їх серед вихідників проекту та бібліотек;
  • Передає інформацію за типами в екземпляри;
  • Вирішує який компілятор повинен виконатися ґрунтуючись на стані екземплярів та загальному стану ресурсів.

Щоб керувати всім і вся, головний компілятор змушує екземпляри кооперуватися. В основному, він вимагає дотримуватися певного набору правил:

  • Синтаксичне дерево має бути доступне до кінця етапу parse2;
  • analyze1повинен мати інформацію про ім'я суперкласу;
  • analyze2повинен знати про всі залежності;
  • analyze4має надавати повну інформацію про тип.

Процес компіляції триває доти:

  • Не залишиться залежностей, які треба дозволити;
  • Примірники компіляторіввидадуть помилку.

Алгоритми виклику

Як було зазначено раніше, процес компіляції складається з виклику цих 9 методів. Але незважаючи на те, що порядок виклику цих методів визначений досить точно, головний компілятор все одно може викликати їх по-різному. По суті, існують 2 алгоритми: Один (flex2.compiler.API.batch1()) структурований, інший (flex2.compiler.API.batch2()) умовно-патогенний. Розглянемо їх окремо:

API.batch1()— консервативний та більш структований алгоритм. Його суть полягає в тому, що він гарантує наступ однієї фази для кожного файлу, перш ніж перейти на іншу фазу. Наприклад,analyze1()буде викликана для всіх файлів, перш ніж перейти доanalyze2().

API.batch2()- умовно-патогенний алгоритм, його головна мета - мінімізувати споживання пам'яті. На відміну відAPI.batch1(), вихідні файли з меншою кількістю залежностей можуть дійти до етапуgenerateнабагато раніше, ніж файли з більшою кількістю залежностей дійдуть до фази analyze3(). Ідея в тому, щоб ресурси, виділені для файлу, могли бути звільнені відразу як файл буде скомпілюваний у байткод.

Висновок

Що ж, тепер Ви знаєте набагато більше про внутрішню роботу компілятора Flex! Давайте підсумуємо:

  • Головний компілятор Flex-а використовує лише один із двох алгоритмів для компіляції: batch1 або batch2;
  • Алгоритми компіляції використовують 2 різні стратегії для виклику 9 етапів складання програми;
  • У процесі компіляції екземпляри компіляторів повинні кооперуватися та надавати інформацію про типи головного компілятора наприкінці кожного етапу;
  • Головний компілятор виконує всю гразну роботу (пошук вихіднихфайлів\бібліотек, управління логуванням помилок і т.д.), а значить компіляторам мов не доводиться турбуватися про це.

Вище актуально для всіх версій утиліт (mxmlc, compc, asdoc), що входять до складу Flex Framework.