forked from KolibriOS/kolibrios
346 lines
20 KiB
Plaintext
346 lines
20 KiB
Plaintext
|
Компилятор языка программирования Oberon-07/16 для x86_64
|
|||
|
Windows/Linux
|
|||
|
------------------------------------------------------------------------------
|
|||
|
|
|||
|
Параметры командной строки
|
|||
|
|
|||
|
Вход - текстовые файлы модулей с расширением ".ob07", кодировка ANSI или
|
|||
|
UTF-8 с BOM-сигнатурой.
|
|||
|
Выход - испоняемый файл формата PE32+ или ELF64.
|
|||
|
Параметры:
|
|||
|
1) имя главного модуля
|
|||
|
2) тип приложения
|
|||
|
"win64con" - Windows64 console
|
|||
|
"win64gui" - Windows64 GUI
|
|||
|
"win64dll" - Windows64 DLL
|
|||
|
"linux64exe" - Linux ELF64-EXEC
|
|||
|
"linux64so" - Linux ELF64-SO
|
|||
|
|
|||
|
3) необязательные параметры-ключи
|
|||
|
-out <file_name> имя результирующего файла; по умолчанию,
|
|||
|
совпадает с именем главного модуля, но с другим расширением
|
|||
|
(соответствует типу исполняемого файла)
|
|||
|
-stk <size> размер стэка в мегабайтах (по умолчанию 2 Мб,
|
|||
|
допустимо от 1 до 32 Мб)
|
|||
|
-nochk <"ptibcwra"> отключить проверки при выполнении
|
|||
|
|
|||
|
параметр -nochk задается в виде строки из символов:
|
|||
|
"p" - указатели
|
|||
|
"t" - типы
|
|||
|
"i" - индексы
|
|||
|
"b" - неявное приведение INTEGER к BYTE
|
|||
|
"c" - диапазон аргумента функции CHR
|
|||
|
"w" - диапазон аргумента функции WCHR
|
|||
|
"r" - эквивалентно "bcw"
|
|||
|
"a" - все проверки
|
|||
|
|
|||
|
Порядок символов может быть любым. Наличие в строке того или иного
|
|||
|
символа отключает соответствующую проверку.
|
|||
|
|
|||
|
Например: -nochk it - отключить проверку индексов и охрану типа.
|
|||
|
-nochk a - отключить все отключаемые проверки.
|
|||
|
|
|||
|
Например:
|
|||
|
|
|||
|
Compiler.exe "C:\example.ob07" win64con -out "C:\example.exe" -stk 1
|
|||
|
Compiler.exe "C:\example.ob07" win64dll -out "C:\example.dll" -nochk pti
|
|||
|
Compiler "source/Compiler.ob07" linux64exe -out "source/Compiler" -nochk a
|
|||
|
|
|||
|
В случае успешной компиляции, компилятор передает код завершения 0, иначе 1.
|
|||
|
|
|||
|
------------------------------------------------------------------------------
|
|||
|
Отличия от оригинала
|
|||
|
|
|||
|
1. Расширен псевдомодуль SYSTEM
|
|||
|
2. В идентификаторах допускается символ "_"
|
|||
|
3. Добавлены системные флаги
|
|||
|
4. Усовершенствован оператор CASE (добавлены константные выражения в
|
|||
|
метках вариантов и необязательная ветка ELSE)
|
|||
|
5. Расширен набор стандартных процедур
|
|||
|
6. Семантика охраны/проверки типа уточнена для нулевого указателя
|
|||
|
7. Добавлены однострочные комментарии (начинаются с пары символов "//")
|
|||
|
8. Разрешено наследование от типа-указателя
|
|||
|
9. Добавлен синтаксис для импорта процедур из внешних библиотек
|
|||
|
10. "Строки" можно заключать также в одиночные кавычки: 'строка'
|
|||
|
11. Добавлен тип WCHAR
|
|||
|
|
|||
|
------------------------------------------------------------------------------
|
|||
|
Особенности реализации
|
|||
|
|
|||
|
1. Основные типы
|
|||
|
|
|||
|
Тип Диапазон значений Размер, байт
|
|||
|
|
|||
|
INTEGER -9223372036854775808 .. 9223372036854775807 8
|
|||
|
REAL 4.94E-324 .. 1.70E+308 8
|
|||
|
CHAR символ ASCII (0X .. 0FFX) 1
|
|||
|
BOOLEAN FALSE, TRUE 1
|
|||
|
SET множество из целых чисел {0 .. 63} 8
|
|||
|
BYTE 0 .. 255 1
|
|||
|
WCHAR символ юникода (0X .. 0FFFFX) 2
|
|||
|
|
|||
|
2. Максимальная длина идентификаторов - 1024 символов
|
|||
|
3. Максимальная длина строковых констант - 1024 символов (UTF-8)
|
|||
|
4. Максимальная размерность открытых массивов - 5
|
|||
|
5. Процедура NEW заполняет нулями выделенный блок памяти
|
|||
|
6. Глобальные и локальные переменные инициализируются нулями
|
|||
|
7. В отличие от многих Oberon-реализаций, сборщик мусора и динамическая
|
|||
|
модульность отсутствуют
|
|||
|
8. Тип BYTE в выражениях всегда приводится к INTEGER
|
|||
|
9. Контроль переполнения значений выражений не производится
|
|||
|
10. Ошибки времени выполнения:
|
|||
|
|
|||
|
1 ASSERT(x), при x = FALSE
|
|||
|
2 разыменование нулевого указателя
|
|||
|
3 целочисленное деление на неположительное число
|
|||
|
4 вызов процедуры через процедурную переменную с нулевым значением
|
|||
|
5 ошибка охраны типа
|
|||
|
6 нарушение границ массива
|
|||
|
7 непредусмотренное значение выражения в операторе CASE
|
|||
|
8 ошибка копирования массивов v := x, если LEN(v) < LEN(x)
|
|||
|
9 CHR(x), если (x < 0) OR (x > 255)
|
|||
|
10 WCHR(x), если (x < 0) OR (x > 65535)
|
|||
|
11 неявное приведение x:INTEGER к v:BYTE, если (x < 0) OR (x > 255)
|
|||
|
|
|||
|
------------------------------------------------------------------------------
|
|||
|
Псевдомодуль SYSTEM
|
|||
|
|
|||
|
Псевдомодуль SYSTEM содержит низкоуровневые и небезопасные процедуры,
|
|||
|
ошибки при использовании процедур псевдомодуля SYSTEM могут привести к
|
|||
|
повреждению данных времени выполнения и аварийному завершению программы.
|
|||
|
|
|||
|
PROCEDURE ADR(v: любой тип): INTEGER
|
|||
|
v - переменная или процедура;
|
|||
|
возвращает адрес v
|
|||
|
|
|||
|
PROCEDURE SADR(x: строковая константа (CHAR UTF-8)): INTEGER
|
|||
|
возвращает адрес x
|
|||
|
|
|||
|
PROCEDURE WSADR(x: строковая константа (WCHAR)): 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: WCHAR, то значение x будет расширено
|
|||
|
до 64 бит, для записи байтов использовать SYSTEM.PUT8,
|
|||
|
для WCHAR -- SYSTEM.PUT16
|
|||
|
|
|||
|
PROCEDURE PUT8(a: INTEGER; x: INTEGER, SET, BYTE, CHAR, WCHAR)
|
|||
|
Память[a] := младшие 8 бит (x)
|
|||
|
|
|||
|
PROCEDURE PUT16(a: INTEGER; x: INTEGER, SET, BYTE, CHAR, WCHAR)
|
|||
|
Память[a] := младшие 16 бит (x)
|
|||
|
|
|||
|
PROCEDURE PUT32(a: INTEGER; x: INTEGER, SET, BYTE, CHAR, WCHAR)
|
|||
|
Память[a] := младшие 32 бит (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,... : BYTE)
|
|||
|
Вставка машинного кода,
|
|||
|
byte1, byte2 ... - константы в диапазоне 0..255,
|
|||
|
например:
|
|||
|
|
|||
|
SYSTEM.CODE(048H,08BH,045H,010H) (* mov rax,qword[rbp+16] *)
|
|||
|
|
|||
|
Также, в модуле SYSTEM определен тип CARD32 (4 байта). Для типа CARD32 не
|
|||
|
допускаются никакие явные операции, за исключением присваивания.
|
|||
|
|
|||
|
Функции псевдомодуля SYSTEM нельзя использовать в константных выражениях.
|
|||
|
|
|||
|
------------------------------------------------------------------------------
|
|||
|
Системные флаги
|
|||
|
|
|||
|
При объявлении процедурных типов и глобальных процедур, после ключевого
|
|||
|
слова PROCEDURE может быть указан флаг соглашения о вызове: [win64], [systemv],
|
|||
|
[windows], [linux].
|
|||
|
Например:
|
|||
|
|
|||
|
PROCEDURE [win64] MyProc (x, y, z: INTEGER): INTEGER;
|
|||
|
|
|||
|
Флаг [windows] - синоним для [win64], [linux] - синоним для [systemv].
|
|||
|
Знак "-" после имени флага ([win64-], [linux-], ...) означает, что
|
|||
|
результат процедуры можно игнорировать (не допускается для типа REAL).
|
|||
|
Если флаг не указан, то принимается внутреннее соглашение о вызове.
|
|||
|
[win64] и [systemv] используются для связи с операционной системой и внешними
|
|||
|
приложениями.
|
|||
|
|
|||
|
При объявлении типов-записей, после ключевого слова 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
|
|||
|
необязательна. Если значение x не соответствует ни одному варианту и ELSE
|
|||
|
отсутствует, то программа прерывается с ошибкой времени выполнения.
|
|||
|
|
|||
|
------------------------------------------------------------------------------
|
|||
|
Тип WCHAR
|
|||
|
|
|||
|
Тип WCHAR добавлен в язык для удобной поддежки юникода. Для типов WCHAR и
|
|||
|
ARRAY OF WCHAR допускаются все те же операции, как для типов CHAR и
|
|||
|
ARRAY OF CHAR, за исключением встроенной процедуры CHR, которая возвращает
|
|||
|
только тип CHAR. Для получения значения типа WCHAR, следует использовать
|
|||
|
процедуру WCHR вместо CHR. Для правильной работы с типом, необходимо сохранять
|
|||
|
исходный код в кодировке UTF-8 c BOM.
|
|||
|
|
|||
|
------------------------------------------------------------------------------
|
|||
|
Проверка и охрана типа нулевого указателя
|
|||
|
|
|||
|
Оригинальное сообщение о языке не определяет поведение программы при
|
|||
|
выполнении охраны p(T) и проверки типа p IS T при p = NIL. Во многих
|
|||
|
Oberon-реализациях выполнение такой операции приводит к ошибке времени
|
|||
|
выполнения. В данной реализации охрана типа нулевого указателя не приводит к
|
|||
|
ошибке, а проверка типа дает результат FALSE. В ряде случаев это позволяет
|
|||
|
значительно сократить частоту применения охраны типа.
|
|||
|
|
|||
|
------------------------------------------------------------------------------
|
|||
|
Дополнительные стандартные процедуры
|
|||
|
|
|||
|
DISPOSE (VAR v: любой_указатель)
|
|||
|
Освобождает память, выделенную процедурой NEW для
|
|||
|
динамической переменной v^, и присваивает переменной v
|
|||
|
значение NIL.
|
|||
|
|
|||
|
COPY (x: ARRAY OF CHAR/WCHAR; VAR v: ARRAY OF CHAR/WCHAR);
|
|||
|
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/WCHAR): INTEGER
|
|||
|
Длина 0X-завершенной строки s, без учета символа 0X.
|
|||
|
Если символ 0X отсутствует, функция возвращает длину
|
|||
|
массива s. s не может быть константой.
|
|||
|
|
|||
|
WCHR (n: INTEGER): WCHAR
|
|||
|
Преобразование типа, аналогично CHR(n: INTEGER): CHAR
|
|||
|
|
|||
|
------------------------------------------------------------------------------
|
|||
|
Импортированные процедуры
|
|||
|
|
|||
|
Синтаксис импорта:
|
|||
|
|
|||
|
PROCEDURE [callconv, "library", "function"] proc_name (FormalParam): Type;
|
|||
|
|
|||
|
- callconv -- соглашение о вызове
|
|||
|
- "library" -- имя файла динамической библиотеки
|
|||
|
- "function" -- имя импортируемой процедуры
|
|||
|
|
|||
|
например:
|
|||
|
|
|||
|
PROCEDURE [win64, "kernel32.dll", "ExitProcess"] exit (code: INTEGER);
|
|||
|
|
|||
|
|
|||
|
В конце объявления может быть добавлено (необязательно) "END proc_name;"
|
|||
|
|
|||
|
Объявления импортированных процедур должны располагаться в глобальной
|
|||
|
области видимости модуля после объявления переменных, вместе с объявлением
|
|||
|
"обычных" процедур, от которых импортированные отличаются только отсутствием
|
|||
|
тела процедуры. В остальном, к таким процедурам применимы те же правила:
|
|||
|
их можно вызвать, присвоить процедурной переменной или получить адрес.
|
|||
|
|
|||
|
Так как импортированная процедура всегда имеет явное указание соглашения о
|
|||
|
вызове, то совместимый процедурный тип тоже должен быть объявлен с указанием
|
|||
|
соглашения о вызове:
|
|||
|
|
|||
|
VAR
|
|||
|
ExitProcess: PROCEDURE [win64] (code: INTEGER);
|
|||
|
|
|||
|
Для Linux, импортированные процедуры не реализованы.
|
|||
|
|
|||
|
------------------------------------------------------------------------------
|
|||
|
Скрытые параметры процедур
|
|||
|
|
|||
|
Некоторые процедуры могут иметь скрытые параметры, они отсутствуют в списке
|
|||
|
формальных параметров, но учитываются компилятором при трансляции вызовов.
|
|||
|
Это возможно в следующих случаях:
|
|||
|
|
|||
|
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. Компилятор транслирует
|
|||
|
некоторые операции (проверка и охрана типа, сравнение строк, сообщения об
|
|||
|
ошибках времени выполнения и др.) как вызовы процедур этого модуля. Не
|
|||
|
следует вызывать эти процедуры явно.
|
|||
|
Сообщения об ошибках времени выполнения выводятся в диалоговых окнах
|
|||
|
(Windows), в терминал (Linux).
|
|||
|
|
|||
|
------------------------------------------------------------------------------
|
|||
|
Модуль API
|
|||
|
|
|||
|
Существуют несколько реализаций модуля API (для различных ОС).
|
|||
|
Как и модуль RTL, модуль API не предназначен для прямого использования.
|
|||
|
Он обеспечивает связь RTL с ОС.
|
|||
|
|
|||
|
------------------------------------------------------------------------------
|
|||
|
Генерация исполняемых файлов DLL
|
|||
|
|
|||
|
Разрешается экспортировать только процедуры. Для этого, процедура должна
|
|||
|
находиться в главном модуле программы, ее имя должно быть отмечено символом
|
|||
|
экспорта ("*") и должно быть указано соглашение о вызове.
|