mirror of
https://github.com/AntKrotov/oberon-07-compiler.git
synced 2026-10-05 09:45:47 +00:00
353 lines
20 KiB
Plaintext
353 lines
20 KiB
Plaintext
Компилятор языка программирования Oberon-07/16 для i386
|
||
Windows/KolibriOS.
|
||
------------------------------------------------------------------------------
|
||
|
||
Параметры командной строки
|
||
|
||
Compiler.exe (Windows), Compiler.kex (KolibriOS) - исполняемый файл
|
||
компилятора.
|
||
Вход - текстовые файлы модулей с расширением ".ob07", кодировка ANSI или
|
||
UTF-8 с BOM-сигнатурой.
|
||
Выход - листинг программы на языке ассемблера fasm.
|
||
Параметры:
|
||
1) имя главного модуля
|
||
2) имя результирующего файла
|
||
3) тип приложения и платформа
|
||
"con" - Windows console
|
||
"gui" - Windows GUI
|
||
"dll" - Windows DLL
|
||
"kos" - KolibriOS
|
||
"obj" - KolibriOS DLL
|
||
4) размер стэка в мегабайтах, необязательный параметр, по умолчанию - 1 Мб.
|
||
|
||
Если 3-й параметр = "obj" (KolibriOS DLL), то 4-й параметр задается в
|
||
формате x.y и определяет версию программы, по умолчанию - 1.0 (v1.0).
|
||
Например:
|
||
|
||
Compiler.exe "C:\oberon-07\example.ob07" "C:\oberon-07\example.asm" con
|
||
Compiler.kex "/tmp0/1/example.ob07" "/tmp0/1/example.asm" obj 2.5 (* v2.5 *)
|
||
|
||
В случае успешной компиляции, компилятор передает код завершения 0, иначе 1.
|
||
При работе компилятора в KolibriOS, код завершения не передается.
|
||
|
||
В файле Compiler.ini можно задать путь к ассеблеру Fasm. Если путь задан
|
||
правильно, то после завершения трансляции, компилятор автоматически вызовет
|
||
fasm для ассемблирования листинга.
|
||
|
||
Пример файла Compiler.ini:
|
||
|
||
_fasm_win "С:\fasmw172\fasm.exe"
|
||
_fasm_kos "/rd/1/develop/fasm"
|
||
|
||
------------------------------------------------------------------------------
|
||
Отличия от оригинала
|
||
|
||
1. Расширен псевдомодуль SYSTEM
|
||
2. В идентификаторах допускается символ "_"
|
||
3. Добавлены системные флаги
|
||
4. Усовершенствован оператор CASE (добавлены константные выражения в
|
||
метках вариантов и необязательная ветка ELSE)
|
||
5. Расширен набор стандартных процедур
|
||
6. Семантика охраны/проверки типа уточнена для нулевого указателя
|
||
7. Семантика DIV и MOD уточнена для отрицательных чисел
|
||
8. Добавлены однострочные комментарии (начинаются с пары символов "//")
|
||
9. Разрешено наследование от типа-указателя
|
||
10. Добавлен синтаксис для импорта процедур из внешних библиотек
|
||
11. "Строки" можно заключать также в одиночные кавычки: 'строка'
|
||
|
||
------------------------------------------------------------------------------
|
||
Особенности реализации
|
||
|
||
1. Основные типы
|
||
|
||
Тип Диапазон значений Размер, байт
|
||
|
||
INTEGER -2147483648 .. 2147483647 4
|
||
REAL 4.94E-324 .. 1.70E+308 8
|
||
CHAR символ ASCII (0X .. 0FFX) 1
|
||
BOOLEAN FALSE, TRUE 1
|
||
SET множество из целых чисел {0 .. 31} 4
|
||
BYTE 0 .. 255 1
|
||
|
||
2. Максимальная длина идентификаторов - 1024 символов
|
||
3. Максимальная длина строковых констант - 1024 символов
|
||
4. Максимальная размерность открытых массивов - 5
|
||
5. Максимальное количество объявленных типов-записей - 2047
|
||
6. Процедура NEW заполняет нулями выделенный блок памяти
|
||
7. Глобальные и локальные переменные инициализируются нулями
|
||
8. В отличие от многих Oberon-реализаций, сборщик мусора и динамическая
|
||
модульность отсутствуют
|
||
9. Тип BYTE в выражениях всегда приводится к INTEGER
|
||
10. Контроль переполнения значений выражений не производится
|
||
11. Ошибки времени выполнения:
|
||
|
||
- ASSERT(x), при x = FALSE
|
||
- разыменование нулевого указателя
|
||
- целочисленное деление на 0
|
||
- вызов процедуры через процедурную переменную с нулевым значением
|
||
- ошибка охраны типа
|
||
- нарушение границ массива
|
||
- непредусмотренное значение выражения в операторе CASE
|
||
- ошибка копирования массивов v := x, если LEN(v) < LEN(x)
|
||
|
||
------------------------------------------------------------------------------
|
||
Псевдомодуль SYSTEM
|
||
|
||
Псевдомодуль SYSTEM содержит низкоуровневые и небезопасные процедуры,
|
||
ошибки при использовании процедур псевдомодуля SYSTEM могут привести к
|
||
повреждению данных времени выполнения и аварийному завершению программы.
|
||
|
||
PROCEDURE ADR(v: любой тип): INTEGER
|
||
v - переменная или процедура;
|
||
возвращает адрес v
|
||
|
||
PROCEDURE SADR(x: строковая константа): INTEGER
|
||
возвращает адрес x
|
||
|
||
PROCEDURE SIZE(T): INTEGER
|
||
возвращает размер типа T
|
||
|
||
PROCEDURE TYPEID(T): INTEGER
|
||
T - тип-запись или тип-указатель,
|
||
возвращает номер типа в таблице типов-записей
|
||
|
||
PROCEDURE INF(): REAL
|
||
возвращает специальное вещественное значение "бесконечность"
|
||
|
||
PROCEDURE GET(a: INTEGER;
|
||
VAR v: любой основной тип, PROCEDURE, POINTER)
|
||
v := Память[a]
|
||
|
||
PROCEDURE PUT(a: INTEGER; x: любой основной тип, PROCEDURE, POINTER)
|
||
Память[a] := x;
|
||
Если x: BYTE, то значение x будет расширено до 32 бит,
|
||
для записи байтов использовать SYSTEM.PUT8
|
||
|
||
PROCEDURE PUT8(a: INTEGER; x: INTEGER, BYTE)
|
||
Память[a] := младший байт (x)
|
||
|
||
PROCEDURE MOVE(Source, Dest, n: INTEGER)
|
||
Копирует n байт памяти из Source в Dest,
|
||
области Source и Dest не должны перекрываться
|
||
|
||
PROCEDURE COPY(VAR Source: любой тип; VAR Dest: любой тип; n: INTEGER)
|
||
Копирует n байт памяти из Source в Dest.
|
||
Эквивалентно
|
||
SYSTEM.MOVE(SYSTEM.ADR(Source), SYSTEM.ADR(Dest), n)
|
||
|
||
PROCEDURE CODE(byte1, byte2,... : INTEGER)
|
||
Вставка машинного кода,
|
||
byte1, byte2 ... - константы в диапазоне 0..255,
|
||
например:
|
||
SYSTEM.CODE(08BH, 045H, 008H) (* mov eax, dword [ebp + 08h] *)
|
||
|
||
Также в модуле SYSTEM определен тип CARD16 (2 байта). Для типа CARD16 не
|
||
допускаются никакие явные операции, за исключением присваивания.
|
||
Преобразования CARD16 -> INTEGER и INTEGER -> CARD16 могут быть реализованы
|
||
так:
|
||
|
||
PROCEDURE Card16ToInt (w: SYSTEM.CARD16): INTEGER;
|
||
VAR i: INTEGER;
|
||
BEGIN
|
||
SYSTEM.PUT(SYSTEM.ADR(i), w)
|
||
RETURN i
|
||
END Card16ToInt;
|
||
|
||
PROCEDURE IntToCard16 (i: INTEGER): SYSTEM.CARD16;
|
||
VAR w: SYSTEM.CARD16;
|
||
BEGIN
|
||
SYSTEM.GET(SYSTEM.ADR(i), w)
|
||
RETURN w
|
||
END IntToCard16;
|
||
|
||
Функции псевдомодуля SYSTEM нельзя использовать в константных выражениях.
|
||
|
||
------------------------------------------------------------------------------
|
||
Системные флаги
|
||
|
||
При объявлении процедурных типов и глобальных процедур, после ключевого
|
||
слова PROCEDURE может быть указан флаг соглашения вызова: [stdcall], [cdecl],
|
||
[winapi] или [kosapi]. Например:
|
||
|
||
PROCEDURE [cdecl] MyProc (x, y, z: INTEGER): INTEGER;
|
||
|
||
Если указан флаг [winapi] или [kosapi], то принимается соглашение stdcall и
|
||
процедуру-функцию можно вызвать как собственно процедуру, вне выражения.
|
||
При объявлении типов-записей, после ключевого слова RECORD может быть
|
||
указан флаг [noalign]. Флаг [noalign] означает отсутствие выравнивания полей
|
||
записи. Записи с системным флагом не могут иметь базовый тип и не могут быть
|
||
базовыми типами для других записей.
|
||
Для использования системных флагов, требуется импортировать SYSTEM.
|
||
|
||
------------------------------------------------------------------------------
|
||
Оператор CASE
|
||
|
||
Синтаксис оператора CASE:
|
||
|
||
CaseStatement =
|
||
CASE Expression OF Сase {"|" Сase}
|
||
[ELSE StatementSequence] END.
|
||
Case = [CaseLabelList ":" StatementSequence].
|
||
CaseLabelList = CaseLabels {"," CaseLabels}.
|
||
CaseLabels = ConstExpression [".." ConstExpression].
|
||
|
||
Например:
|
||
|
||
CASE x OF
|
||
|-1: DoSomething1
|
||
| 1: DoSomething2
|
||
| 0: DoSomething3
|
||
ELSE
|
||
DoSomething4
|
||
END
|
||
|
||
В метках вариантов можно использовать константные выражения, ветка ELSE
|
||
необязательна. Если не выполнен ни один вариант и ELSE отсутствует, то
|
||
программа прерывается с ошибкой времени выполнения.
|
||
|
||
------------------------------------------------------------------------------
|
||
Проверка и охрана типа нулевого указателя
|
||
|
||
Оригинальное сообщение о языке не определяет поведение программы при
|
||
выполнении охраны p(T) и проверки типа p IS T при p = NIL. Во многих
|
||
Oberon-реализациях выполнение такой операции приводит к ошибке времени
|
||
выполнения. В данной реализации охрана типа нулевого указателя не приводит к
|
||
ошибке, а проверка типа дает результат FALSE. В ряде случаев это позволяет
|
||
значительно сократить частоту применения охраны типа.
|
||
|
||
------------------------------------------------------------------------------
|
||
Дополнительные стандартные процедуры
|
||
|
||
DISPOSE(VAR v: любой_указатель)
|
||
Освобождает память, выделенную процедурой NEW для
|
||
динамической переменной v^, и присваивает переменной v
|
||
значение NIL.
|
||
|
||
COPY(x: ARRAY OF CHAR; VAR v: ARRAY OF CHAR);
|
||
v := x;
|
||
Если LEN(v) < LEN(x), то строка x будет скопирована
|
||
не полностью
|
||
|
||
LSR(x, n: INTEGER): INTEGER
|
||
Логический сдвиг x на n бит вправо.
|
||
|
||
MIN(a, b: INTEGER): INTEGER
|
||
Минимум из двух значений.
|
||
|
||
MAX(a, b: INTEGER): INTEGER
|
||
Максимум из двух значений.
|
||
|
||
BITS(x: INTEGER): SET
|
||
Интерпретирует x как значение типа SET.
|
||
Выполняется на этапе компиляции.
|
||
|
||
LENGTH(s: ARRAY OF CHAR): INTEGER
|
||
Длина 0X-завершенной строки s, без учета символа 0X.
|
||
Если символ 0X отсутствует, функция возвращает длину
|
||
массива s.
|
||
|
||
------------------------------------------------------------------------------
|
||
DIV и MOD
|
||
|
||
x y x DIV y x MOD y
|
||
|
||
5 3 1 2
|
||
-5 3 -2 1
|
||
5 -3 -2 -1
|
||
-5 -3 1 -2
|
||
|
||
------------------------------------------------------------------------------
|
||
Импортированные процедуры
|
||
|
||
Синтаксис импорта:
|
||
|
||
PROCEDURE [callconv, "library", "function"] proc_name (FormalParam): Type;
|
||
|
||
- callconv -- соглашение вызова (stdcall, cdecl, winapi, kosapi)
|
||
- "library" -- имя файла динамической библиотеки
|
||
- "function" -- имя импортируемой процедуры
|
||
|
||
например:
|
||
|
||
PROCEDURE [winapi, "kernel32.dll", "ExitProcess"] exit (code: INTEGER);
|
||
|
||
PROCEDURE [stdcall, "Console.obj", "con_exit"] exit (bCloseWindow: BOOLEAN);
|
||
|
||
Объявления импортированных процедур должны располагаться в глобальной
|
||
области видимости модуля после объявления переменных, вместе с объявлением
|
||
"обычных" процедур, от которых импортированные отличаются только отсутствием
|
||
тела процедуры. В остальном, к таким процедурам применимы те же правила:
|
||
их можно вызвать, присвоить процедурной переменной или получить адрес.
|
||
|
||
Так как импортированная процедура всегда имеет явное указание соглашения
|
||
вызова, то совместимый процедурный тип тоже должен быть объявлен с указанием
|
||
соглашения вызова:
|
||
|
||
VAR
|
||
ExitProcess: PROCEDURE [winapi] (code: INTEGER);
|
||
con_exit: PROCEDURE [stdcall] (bCloseWindow: BOOLEAN);
|
||
|
||
В KolibriOS импортировать процедуры можно только из библиотек, размещенных
|
||
в /rd/1/lib. Импортировать и вызывать функции инициализации библиотек
|
||
(lib_init, START) при этом не нужно.
|
||
|
||
------------------------------------------------------------------------------
|
||
Скрытые параметры процедур
|
||
|
||
Некоторые процедуры могут иметь скрытые параметры, они отсутствуют в списке
|
||
формальных параметров, но учитываются компилятором при трансляции вызовов.
|
||
Это возможно в следующих случаях:
|
||
|
||
1. Процедура имеет формальный параметр открытый массив:
|
||
PROCEDURE Proc (x: ARRAY OF ARRAY OF REAL);
|
||
Вызов транслируется так:
|
||
Proc(LEN(x), LEN(x[0]), SYSTEM.ADR(x))
|
||
2. Процедура имеет формальный параметр-переменную типа RECORD:
|
||
PROCEDURE Proc (VAR x: Rec);
|
||
Вызов транслируется так:
|
||
Proc(SYSTEM.TYPEID(Rec), SYSTEM.ADR(x))
|
||
|
||
------------------------------------------------------------------------------
|
||
Модуль RTL
|
||
|
||
Все программы неявно используют модуль RTL. Компилятор транслирует
|
||
некоторые операции (проверка и охрана типа, сравнение строк, сообщения об
|
||
ошибках времени выполнения и др.) как вызовы процедур этого модуля. Не
|
||
следует явно вызывать эти процедуры, за исключением процедуры SetDll,
|
||
если приложение компилируется как Windows DLL:
|
||
|
||
PROCEDURE SetDll
|
||
(process_detach, thread_detach, thread_attach: DLL_ENTRY);
|
||
где TYPE DLL_ENTRY =
|
||
PROCEDURE [stdcall] (hinstDLL, fdwReason, lpvReserved: INTEGER);
|
||
|
||
SetDll назначает процедуры process_detach, thread_detach, thread_attach
|
||
вызываемыми при
|
||
- выгрузке dll-библиотеки (process_detach)
|
||
- создании нового потока (thread_attach)
|
||
- уничтожении потока (thread_detach)
|
||
|
||
Для прочих типов приложений, вызов процедуры SetDll не влияет на
|
||
поведение программы.
|
||
Сообщения об ошибках времени выполнения выводятся в диалоговых окнах
|
||
(Windows), на доску отладки (KolibriOS).
|
||
|
||
------------------------------------------------------------------------------
|
||
Модуль API
|
||
|
||
Существуют две реализации модуля API: для Windows и для KolibriOS. Как и
|
||
модуль RTL, модуль API не предназначен для прямого использования. Он
|
||
обеспечивает кроссплатформенность компилятора.
|
||
|
||
------------------------------------------------------------------------------
|
||
Генерация исполняемых файлов DLL
|
||
|
||
Разрешается экспортировать только процедуры. Для этого, процедура должна
|
||
находиться в главном модуле программы, и ее имя должно быть отмечено символом
|
||
экспорта ("*"). KolibriOS DLL всегда экспортируют идентификаторы "version"
|
||
(версия программы) и "lib_init" - адрес процедуры инициализации DLL:
|
||
|
||
PROCEDURE [stdcall] lib_init (): INTEGER
|
||
|
||
Эта процедура должна быть вызвана перед использованием DLL.
|
||
Процедура всегда возвращает 1. |