Проект Оберс -> транслятор | Linguage: Ukrainian English |
Командний рядок має наступний вигляд:
obers fname { -dDNAMEz }, де:
- fname - ім'я файла для трансляції вказане без розширення;
- DNAME - ім'я директиви;
- z - знак ("+" - увімкнути, "-" - вимкнути).
Транслятор завжди додає до fname розширення O2, тому файли ваших програм повинні його мати.
Зарезервовані імена директив для транслятора наступні:
Ви можете додавати власні директиви. Вони не вплинуть на трансляцію, але будуть перенесені у вихідний файл на макроасемблері. Таким чином можна впливати на процес асемблювання програми.
Приклади:
Коли транслятор закінчує роботу він повертає операційній системі код завершення. Код ноль означає що все гаразд, інший код - код помилки. Щоб отримувати текст пояснень на конкретний код передбачен пакетний файл obers.bat. При його використанні командний рядок має наступний вигляд:
obers fname, де:
- fname - ім'я файла для трансляції вказане без розширення.
Ви мусите пам'ятати, що розширення bat в ДОС має більший пріорітет ніж com, тому для виклику транслятора треба буде застосовувати команду:
obers.com fname
Використання пакетного файла для роздруковки тексту помилки має одну перевагу: ви легко можете перекласти цей файл на свою національну мову, наприклад - турецьку.
Спочатку відкривається файл (модуль) X заданий у командному рядку. Якщо він має оператор IMPORT Y, то транслятор: зберігає поточну позицію читання в файлі, зберігає директиви трансляції, закриває поточний файл, відкриває файл модуля Y, встановлє директиви трансляції задані в командному рядку. Після обробки файла Y відбувається повернення до файла X. Вкладеність модулів обмежується тільки доступною пам'яттю. Якщо модулі X та Y імпортують модуль Z, то модуль (файл) Z буде оброблено лише перший раз, при цьому відомості про експортовані імена з нього будуть збережені. При повторному включенні модуля Z транслятор лише дозволить викликаючому модулю доступ до збережених даних.
Якщо в програмі існують вирази в яких фігурують лише константи, то вони будуть обчислені транслятором. Наприклад:
x:=1+3*5-ABS(-6);
i x:=10;
дають однаковий код;x:=1+3*5-ABS(-6)+y;
i x:=10+y;
дають однаковий код;x:=1+3*5-y-ABS(-6);
i x:=10-y;
дають різний код
(який поверне однаковий результат під час виконання).Циклічний імпорт модулів, як відомо з визначення мови Оберон-2, заборонений. Тобто якщо в модулі X є оператор IMPORT Y, то модуль Y, не може містити оператор IMPORT X.
Транслятор не підтримує роздільну трансляцію, тому ви повинні мати тексти всіх програмних модулів які використовуєте.
Транслятор не вживає в вихідному файлі імен, які ви дали програмним об'єктам (змінним, підпрограмам, ...). Це пов'язано з тим, що у модулях можуть бути однакові імена, які мають різний зміст, а вихідний файл створюється один.
Хоча розширення мови програмування і не сприяє переносу програм між різними компіляторами, але іноді воно спрощує життя. Тому остаточний вибір залишається за вами.
"Головним розширенням" транслятора obers є підтримка імен на національних мовах. Тому ви можете, наприклад, написати такий оператор:
сума:=доданок1+доданок2;
До дозволених літер потрапили також зворотній апостроф (код 96) і знак підкреслення (код 95). Всі символи з 128 по 255 також є дозволеними. Мотивація розширення наступна: більша зрозумілість програми.
Розширенням в трансляторі також є робота стандартної функції CAP(x:CHAR) - перевести літеру у верхній регістр. Проблема в тому, чим буде її аргумент: константою, чи змінною. Якщо в вашій програмі є рядок:
буква:=CAP("я");
,
то змінній типа CHAR буде привласнено значення "Я". Кодування літер кирилиці у трансляторі відбувається за кодовою сторінкою 866 (український, російський та білоруський алфавіти). Якщо в вашій програмі є рядок:
буква:=CAP(буква);
,
то перевід у верхній регістр буде виконано (під час виконання програми) за таблицею, яка знаходилася у файлі macro.mac. Якщо ви змінили цю таблицю, ваші результати не співпадатимуть. Мотивація цього розширення: спрощення прикладних програм.
Транслятор obers надає можливість створювати так звані кодові підпрограми (code procedures). Це розширення рекомендується в Oakwood Guidelines, розділ 3.4. Синтаксис її визначен як:
PROCEDURE -ProcHeading byte {"," byte};
Отже, перед ім'ям процедури ви повинні поставити знак "-", а після заголовка процедури повинна йти через кому непорожня послідовність байтів - чисел з діапазону [0..255]. Завершується така процедура крапкою з комою. Наприклад:
PROCEDURE -ln (x: REAL): REAL; (* log2(x)/log2(e) *)
0D9H,0EDH, (* fldln2 *)
0D9H,044H,024H,004H, (* fld dword[esp+4] *)
0D9H,0F1H, (* fyl2x *)
0C2H,004H,000H; (* ret 4 *)
Коментарі в дужках не обов'язкові.
Природньо, що такі підпрограми не є переносимими. Наприклад, наведена вище фунція ln не буде працювати в 16-розрядному режимі процесорів 80x86, крім того вона використовує інструкції сопроцесора 80x87. Мотивацією застосування таких підпрограм є білша гнучкість та ефективність кода. Кодовими процедурами можна скористатися для включення в програму ресурсів.
Ще одним розширенням є можливість керувати ходом трансляції. Вона визначена у розділі 4.0 Oakwood Guidelines. Докладніше вона обговорюється у розділі Керування ходом трансляції та опції транслятора.
Останнім розширенням, є підпрограми додані в модуль SYSTEM. Цей модуль включений в програму транслятора і не є зовнішнім файлом. Викликано це тим, що процедури цього модуля фактично є макросами, і їх заголовки не завжди можна визначити засобами мови. Модуль слугує меті полегшення системного програмування. Імена доданих процедур такі: Install, CLI, STI, PORTIN, PORTOUT. Докладніше додані підпрограми обговорюються у розділі Розширення модуля SYSTEM.
Керування ходом трансляції та опції транслятора
Дане розширення описане в Oakwood Guidelines, розділах 4.3 і 4.4. Потрібно воно для серйозних проектів, а суть є такою: у програмі є невеличкі місця які треба запрограмувати по різному в залежності від обставин. При цьому вам не хочеться створювати новий файл. У поточній реалізації транслятора obers не розрізняються опції (options) і селектори (selectors), тому що синтаксис їх використання тотожній і всі вони потрапляють у вихідний файл на асемблері. Тому надалі я писатиму леше про селектори.
Для керування процесом трансляції потрібні ознаки - селектори. У трансляторі obers вони можуть бути задані двома способами: з командного рядка і безпосередньо в тексті. Перший способ був описаний вище. Другий спосіб має такий сінтаксис:
<* NEW SelectorName *>
Селектори задані в командному рядку є дійсними для всіх файлів що транслюються. Задані в тексті - тільки в поточному файлі.
Селектори можуть мати тільки два значення: увімкнено (true) і вимкнено (false). Задати значення можна наступним чином:
<* SelectorName+ *>
- увімкнути
<* SelectorName- *>
- вимкнути
Для перевірки селекторів і виконання дій по включенню-виключенню фрагментів текста вашої програми, слугує спеціальний умовний оператор IF. За логікою роботи він не відрізняється від штатного умовного оператора Оберона. Нижче схематично наведено його найбільш загальне використання.
<* IF умова THEN *>
рядки вашої програми
<* ELSIF умова THEN *>
рядки вашої програми
<* ELSE *>
рядки вашої програми
<* END *>
Допустимі оператори у виразі умова є ~, & i OR. Їхня дія аналогічна дії операторів Оберона з тимиж самими іменами.
Невеличкий приклад. Припустимо, вам треба обчислювати по формулі x = x * 2. Ви знаєте, що на процесорі А швидше виконується варіант INC(x,x), а на процесорі Б - x:=ASH(x,1). Йти та компроміс ви не хочете, і мати два різних файли для однієї програми теж. Вихід такий:
<* IF ProcA THEN *>
INC(x,x);
<* ELSE *>
x:=ASH(x,1);
<* END *>
Транслюючи програму командой
obers.com HELLO -dProcA+,
ви матимете перший варіант кода, а командой
obers.com HELLO -dProcA-
- другий варіант.
За думкою авторів мови Оберон-2, в модуль SYSTEM повинні бути винесені речі, які не є стандартними для всіх платформ. У Oakwood Guidelines розділ 5.3, пропонується прийняти цей модуль за основу і розширяти коли потрібно. Я додав у модуль такі процедури.
Об'яви цих процедур наступні:
PROCEDURE CLI;
PROCEDURE STI;
PROCEDURE Install (proc: PROCEDURE; num: байт);
PROCEDURE PORTIN (port: LONGINT; VAR x: Type1);
PROCEDURE PORTOUT (port: LONGINT; x: Type1);
Під Type1 розуміється любий основний тип (крім LONGREAL), вказівник, або процедурний тип. Під байт - ціле число в диапазоні [0..255].
Підпрограма Install виконує важливі системні речі - встановлює опрацьовувач переривання. Нагадаю, що мова Оберон-2 вимагає, щоб підпрограми які передаються як параметри, не можуть бути пов'язані з типом, бути стандартною або локальною в іншій підпрограмі.
Кодові підпрограми, згадані вище, можна використати для включення в програму різних ресурсів, наприклад шрифтів або малюнків. Можете застосувати для цього програму createrm.com. Її командний рядок:
createrm resursdef,
де resursdef - ім'я файла визначення ресурсів.
Файл ресурсів повинен бути складеним за наступними правилами.
Наприклад, якщо задан командний рядок:
createrm mres.res,
а в файлі mres.res розміщено такий текст:
proba _size
Resurs1 text.ico 0 0
Resurs2 text.ico 100 10H
Resurs3 readme.txt 0 0
то буде створено файл proba.O2, який матиме наступний текст (схематично):
MODULE proba;
CONST
Resurs1_size- = 766;
Resurs2_size- = 16;
Resurs3_size- = 888;
PROCEDURE -Resurs1-;
000H,000H,001H,...;
PROCEDURE -Resurs2-;
000H,000H,001H,...;
PROCEDURE -Resurs3-;
020H,020H,025H,...;
END proba.
Вираз
FOR i:=0 TO proba.Resurs3_size-1 DO SYSTEM.GET(SYSTEM.ADR(proba.Resurs3)+i,x) END
послідовно зчитує всі байти файла readme.txt, для того, наприклад, щоб відобразити їх на екрані.