﻿        Компилятор языка программирования Oberon-07/11 для x86-32
                Windows/Linux/KolibriOS.
------------------------------------------------------------------------------

        Состав программы

1.      Compiler.exe (Windows), Compiler (Linux), Compiler.kex (KolibriOS) -
        исполняемый файл компилятора.
        Вход - текстовые файлы модулей с расширением ".ob07", кодировка ANSI
        или UTF-8 с BOM-сигнатурой.
        Выход - исполняемый файл формата PE, ELF или MENUET01/MS COFF.
        Параметры:
        1) имя главного модуля
        2) тип приложения и платформа
                "con" - Windows console
                "gui" - Windows GUI
                "dll" - Windows DLL
                "elf" - Linux
                "kos" - KolibriOS
                "obj" - KolibriOS DLL
        3) размер стэка в мегабайтах, необязательный параметр, по умолчанию -
        1 Мб, для ELF игнорируется. Если 2-й параметр = "obj" (KolibriOS DLL),
        то 3-й параметр задается шестнадцатиричным числом
        (0x00000001 .. 0xffffffff) и определяет версию программы,
        по умолчанию - 0x00010000 (v1.0).
        Например:
                "C:\oberon-07\example.ob07" con 2
                "C:\oberon-07\example.ob07" obj 0x00020005 (* v2.5 *)
        В случае успешной компиляции, компилятор передает код завершения 0,
        иначе 1. При работе компилятора в KolibriOS, код завершения не
        передается. Сообщения компилятора выводятся на консоль (Windows,
        KolibriOS), в терминал (Linux).

2.      папка Lib - стандартные модули

3.      папка Source - исходный код компилятора

------------------------------------------------------------------------------
        Отличия от оригинала

1.      Расширен псевдомодуль SYSTEM
2.      Разрешен символ "_" в идентификаторах
3.      Добавлены системные флаги
4.      Оператор CASE реализован в соответствии с синтаксисом и семантикой
        данного оператора в языке Oberon (Revision 1.10.90)
5.      Расширен набор стандартных процедур
6.      Семантика охраны/проверки типа уточнена для нулевого указателя
7.      Семантика DIV и MOD уточнена для отрицательных чисел
8.      Добавлены однострочные комментарии (начинаются с пары символов "//")
9.      Разрешен экспорт переменных типов ARRAY и RECORD (только для чтения)
10.     Разрешено наследование от типа-указателя
11.     Добавлены псевдонимы типов (TYPE A = B)

------------------------------------------------------------------------------
        Особенности реализации

1.      Основные типы

          Тип              Диапазон значений               Размер, байт

        INTEGER       -2147483648 .. 2147483647                 4
        REAL          1.40E-45 .. 3.34E+38                      4
        LONGREAL      4.94E-324 .. 1.70E+308                    8
        CHAR          символ ASCII (0X .. 0FFX)                 1
        BOOLEAN       FALSE, TRUE                               1
        SET           множество из целых чисел {0 .. 31}        4

2.      Максимальная длина идентификаторов - 255 символов
3.      Максимальная длина строковых констант - 255 символов
4.      Максимальная длина строк исходного кода - 511 символов
5.      Максимальная размерность открытых массивов - 5
6.      Максимальное количество объявленных типов-записей - 2047
7.      Процедура NEW заполняет нулями выделенный блок памяти
8.      Глобальные и локальные переменные инициализируются нулями
9.      В отличие от многих Oberon-реализаций, сборщик мусора и динамическая
        модульность отсутствуют

------------------------------------------------------------------------------
        Псевдомодуль SYSTEM

  Псевдомодуль SYSTEM содержит низкоуровневые и небезопасные процедуры,
ошибки при использовании процедур псевдомодуля SYSTEM могут привести к
повреждению данных времени выполнения и аварийному завершению программы.

        PROCEDURE ADR(v: любой тип): INTEGER
                v - переменная, процедура или строковая константа;
                возвращает адрес v

        PROCEDURE SIZE(T): INTEGER
                возвращает размер типа T

        PROCEDURE TYPEID(T): INTEGER
                T - тип-запись или тип-указатель,
                возвращает номер типа в таблице типов-записей

        PROCEDURE INF(T): T
                T - REAL или LONGREAL,
                возвращает специальное вещественное значение "бесконечность"

        PROCEDURE GET(a: INTEGER;
                VAR v: любой основной тип, PROCEDURE, POINTER)
                v := Память[a]

        PROCEDURE PUT(a: INTEGER; x: любой основной тип, PROCEDURE, POINTER)
                Память[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(s: ARRAY OF CHAR)
                Вставка машинного кода
                s - строковая константа шестнадцатиричных цифр
                количество цифр должно быть четным
                например: SYSTEM.CODE("B801000000") (* mov eax, 1 *)

  Также в модуле 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]. Например:

        PROCEDURE [cdecl] MyProc(x, y, z: INTEGER): INTEGER;

  Если указан флаг [winapi], то принимается соглашение stdcall и
процедуру-функцию можно вызвать как собственно процедуру, вне выражения.
Флаг [winapi] доступен только для платформы Windows.
  При объявлении типов-записей, после ключевого слова RECORD может быть
указан флаг [noalign] или [union]. Флаг [noalign] означает отсутствие
выравнивания полей записи, а флаг [union] означает, что смещения всех полей
записи равны нулю, при этом размер записи равен размеру наибольшего поля.
Записи RECORD [union] ... END соответствуют объединениям (union) в языке C.
Записи с системными флагами не могут иметь базового типа и не могут быть
базовыми типами для других записей.
  Для использования системных флагов, требуется импортировать 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.

        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

------------------------------------------------------------------------------
        Скрытые параметры процедур

  Некоторые процедуры могут иметь скрытые параметры, они отсутствуют в списке
формальных параметров, но учитываются компилятором при трансляции вызовов.
Это возможно в следующих случаях:

1.      Процедура имеет формальный параметр открытый массив:
                PROCEDURE Proc(x: ARRAY OF ARRAY OF LONGREAL);
        Вызов транслируется так:
                Proc(SYSTEM.ADR(x), LEN(x), LEN(x[0])
2.      Процедура имеет формальный параметр-переменную типа RECORD:
                PROCEDURE Proc(VAR x: Rec);
        Вызов транслируется так:
                Proc(SYSTEM.TYPEID(Rec), SYSTEM.ADR(x))
3.      Процедура является вложенной, глубина вложения k,
        для глобальных процедур k = 0:
                PROCEDURE Proc(p1, ..., pn);
        Вызов транслируется так:
                Proc(base(k - 1), base(k - 2), ..., base(0), p1, ..., pn),
        где base(m) - адрес базы кадра стэка охватывающей процедуры глубины
        вложения m (используется для доступа к локальным переменным
        охватывающей процедуры)

------------------------------------------------------------------------------
        Модуль RTL

  Все программы неявно используют модуль RTL. Компилятор транслирует
некоторые операции (проверка и охрана типа, сравнение строк, сообщения об
ошибках времени выполнения и др.) как вызовы процедур этого модуля. Не
следует явно вызывать эти процедуры, за исключением процедуры SetClose:

        PROCEDURE SetClose(proc: PROC), где TYPE PROC = PROCEDURE

SetClose назначает процедуру proc (без параметров) вызываемой при выгрузке
dll-библиотеки (Windows), если приложение компилируется как Windows DLL. Для
прочих типов приложений и платформ вызов процедуры SetClose не влияет на
поведение программы.
  Сообщения об ошибках времени выполнения выводятся в диалоговых окнах
(Windows), в терминал (Linux), на доску отладки (KolibriOS).

------------------------------------------------------------------------------
        Модуль API

  Существуют три реализации модуля API: для Windows, Linux и KolibriOS. Как и
модуль RTL, модуль API не предназначен для прямого использования. Он
обеспечивает кроссплатформенность компилятора.

------------------------------------------------------------------------------
        Генерация исполняемых файлов DLL

  Разрешается экспортировать только процедуры. Для этого, процедура должна
находиться в главном модуле программы, и ее имя должно быть отмечено символом
экспорта ("*"). KolibriOS DLL всегда экспортируют идентификаторы "version"
(версия программы) и "lib_init" - адрес процедуры инициализации DLL:

        PROCEDURE [stdcall] lib_init(): INTEGER

Эта процедура должна быть вызвана перед использованием DLL.
Процедура всегда возвращает 1.
  В настоящее время генерация DLL для Linux не реализована.