MXML компілятор
Ще одна копія хабора
Головне меню
Навігація за записами
MXML компілятор. Частина 3. Розбираємось у роботі Flex-компілятора
Як завжди всіх, хто не втомився дочитавши до цього рядка - прошу під кат! По-перше, вважаю доречним навести посилання на інші статті з циклу:
По-друге, мені довелося досить добре погуглить щоб знайти актуальне (у зв'язку з передачею Flex-а апачам) посилання на код гілки 4.6, і щоб заощадити Ваш час я просто залишу її тут: opensource.adobe.com/svn //opensource/flex/sdk/branches/4.y/
Компілятори мов
Взагалі Flex компілятор підтримує різні мови програмування. Компілюються вони набором специфічних кожної мови компіляторами. Якщо ви побачите список класів проекту з ім'ям Compiler, можна побачити деякі з них:

Так само розумно припускати, що різним компіляторам потрібна різна кількість етапів. Наприклад, MXML компілятор вимагає вдвічі більше кроків ніж AS3.
flex2.compiler.SubCompiler
У Flex, всі компілятори мов реалізують той самий інтерфейс -flex2.compiler.SubCompiler:
З методів, що не належать до процесу компіляції, можна виділити:String getName()— як можна зрозуміти з назви, метод повертає ім'я компілятора;isSupportedтаgetSupportedMimeTypes— служать для визначення типу файлів, якіцей компілятор може обертати; benchmarks методи, що відносяться до вимірювання продуктивності компіляції.
Етапи компіляції
Як Ви помітили, процес компіляції складається з 9 етапів. Головний Flex-компілятор виступає в ролі координатора і відповідає за виклик екземплярів компіляторів, які очікують приблизно такого порядку:
- preprocess (один раз)
- parse1 (один раз)
- parse2 (один раз)
- analyze1 (один раз)
- analyze2 (один раз)
- analyze3 (один раз)
- analyze4 (один раз)
- generate (один раз)
- 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.