Компилятор Oberon-07

High-level languages programming questions
  • Как следует из документации:
    Параметры:
    ..............
    3) тип приложения и платформа
    ..............
    "obj" - KolibriOS DLL
    Разрешается экспортировать только процедуры.
    ..............
    KolibriOS DLL всегда экспортируют идентификаторы "version"
    (версия программы) и "lib_init" - адрес процедуры инициализации DLL:

    PROCEDURE [stdcall] lib_init (): INTEGER

    Эта процедура должна быть вызвана перед использованием DLL.
    Если видел примеры для XDS Modula-2/Oberon-2 compiler http://board.kolibrios.org/viewtopic.php?f=33&t=2280 то там сначала получается объектный файл, затем он линкуется с другими модулями примерно так:

    Code: Select all

              xc %name%.mod -objfmt=coff
              ld -o              %Name%.kex ^
                 -T            ../LScript.x ^
                                 %Name%.obj ^
                      ../../Modules/DLL.obj ^
                      ../../Modules/X2C.obj ^
                    ../../Modules/InOut.obj
    Сейчас нет возможности использовать сторонние модули при статической линковке.
    akron1 wrote:- Добавлен специальный синтаксис для импорта функций из динамических библиотек.
    Теперь подсветка в HippoEDIT "поехала".
  • Я пока плохо представляю, как работает статическая линковка. Если будет время и желание, то может быть сделаю раздельную компиляцию с последующей линковкой. Но видимо нескоро. Сейчас мне это кажется довольно сложным.
    0CodErr wrote:Теперь подсветка в HippoEDIT "поехала".
    Если есть какие-либо идеи, то можешь предложить свой вариант синтаксиса импорта, более удобный для подсветки.
  • akron1 wrote:Если будет время и желание, то может быть сделаю раздельную компиляцию с последующей линковкой. Но видимо нескоро.
    Ну ничего страшного, торопиться и не надо :)
    Если будет что — с удовольствием потестирую.
    akron1 wrote:предложить свой вариант синтаксиса импорта, более удобный для подсветки
    Казалось бы, банальное добавление END; решает проблему

    Code: Select all

    PROCEDURE [winapi, "kernel32.dll", "GetTickCount"]
        _GetTickCount* (): INTEGER; END;
    
    PROCEDURE [winapi, "kernel32.dll", "GetStdHandle"]
        GetStdHandle (nStdHandle: INTEGER): INTEGER; END;
    
    PROCEDURE [winapi, "kernel32.dll", "GetCommandLineA"]
        GetCommandLine (): INTEGER; END;
    
    PROCEDURE [winapi, "kernel32.dll", "ReadFile"]
        ReadFile (hFile, Buffer, nNumberOfBytesToRW: INTEGER; VAR NumberOfBytesRW: INTEGER; lpOverlapped: POverlapped): INTEGER; END;
    
    PROCEDURE [winapi, "kernel32.dll", "WriteFile"]
        WriteFile (hFile, Buffer, nNumberOfBytesToRW: INTEGER; VAR NumberOfBytesRW: INTEGER; lpOverlapped: POverlapped): INTEGER; END;
    
    PROCEDURE [winapi, "kernel32.dll", "CloseHandle"]
        CloseHandle (hObject: INTEGER): INTEGER; END;
    
    PROCEDURE [winapi, "kernel32.dll", "CreateFileA"]
        CreateFile (
            lpFileName, dwDesiredAccess, dwShareMode: INTEGER;
            lpSecurityAttributes: PSecurityAttributes;
            dwCreationDisposition, dwFlagsAndAttributes,
            hTemplateFile: INTEGER): INTEGER; END;
    
    PROCEDURE [winapi, "kernel32.dll", "OpenFile"]
        OpenFile (lpFileName: INTEGER; lpReOpenBuff: OFSTRUCT; uStyle: INTEGER): INTEGER; END;
    
    PROCEDURE [winapi, "kernel32.dll", "ExitProcess"]
        ExitProcess* (code: INTEGER); END;
    
    PROCEDURE [winapi, "shell32.dll", "ShellExecuteA"]
        ShellExecute* (hWnd, Operation, FileName, Parameters, Directory, ShowCmd: INTEGER): INTEGER; END;
    
    Не знаю, уж насколько логично это выглядит.
    akron1 wrote:Кроссплатформенные примеры скоро будут.
    Будет ли возможность собрать те примеры(Projects.7z ) http://board.kolibrios.org/viewtopic.ph ... =45#p70389 ?
  • END, конечно, не очень красиво. Хотя, можно сделать (опционально):

    Code: Select all

    PROCEDURE [winapi, "kernel32.dll", "CloseHandle"]
        CloseHandle* (hObject: INTEGER): INTEGER;
    END CloseHandle;
    
    Будет ли возможность собрать те примеры(Projects.7z )
    Да, я поставлю заглушки для Windows Console.open, Console.exit. Вроде бы ничего лучше пока нельзя сделать. Еще надо будет сделать поддержку относительных путей, чтобы компилировать из командного файла.
  • akron1 wrote:Я пока плохо представляю, как работает статическая линковка. Если будет время и желание, то может быть сделаю раздельную компиляцию с последующей линковкой. Но видимо нескоро. Сейчас мне это кажется довольно сложным.
    Это проще чем звучит. Функции выкладываются по очереди в сегмент кода, их адреса запоминаются.
    На втором проходе по местам релоков прописываются полученные адреса.

    Вот как сделано в tcc, всего 300 строк

    Меня наоборот, пугает динамическая =)
  • akron1 wrote:END, конечно, не очень красиво. Хотя, можно сделать (опционально):

    Code: Select all

    PROCEDURE [winapi, "kernel32.dll", "CloseHandle"]
        CloseHandle* (hObject: INTEGER): INTEGER;
    END CloseHandle;
    
    Сделано.
    akron1 wrote:
    Будет ли возможность собрать те примеры(Projects.7z )
    Да, я поставлю заглушки для Windows Console.open, Console.exit. Вроде бы ничего лучше пока нельзя сделать.
    Сделано.
    akron1 wrote: Еще надо будет сделать поддержку относительных путей
    Сделано.

    Примеры прикрепил.
    Attachments
    Projects.zip (13.3 KiB)
    Downloaded 380 times
  • akron1 wrote:заглушки для Windows Console.open, Console.exit. Вроде бы ничего лучше пока нельзя сделать.
    Разве нельзя было инициализировать консоль внутри In.Open и Out.Open?
    Раньше ещё поддерживался Linux, теперь он поддерживаться не будет?
  • Ну а финализацию куда всунуть? Я так думаю, что инициализация и финализация консоли должны быть в одном модуле. Я выбрал модуль Console. Другое дело, что Console.open фактически не нужно вызывать в Windows, а In.Open и Out.Open не нужны в KolibriOS (In.Open, правда, инициализирует переменную Done, но этот код можно перенести в секцию инициализации модуля In). Я тут думаю, что может быть лучше In.Open и Out.Open вызывать из Console.open.

    Тогда "кроссплатформенный" код главного модуля будет выглядеть так:

    Code: Select all

    MODULE program;
    
    IMPORT C := Console, In, Out;
    
    BEGIN
        C.open;
    
        C.exit(TRUE)
    END program.
    
    вместо

    Code: Select all

    MODULE program;
    
    IMPORT C := Console, In, Out;
    
    BEGIN
        C.open;
        In.Open;
        Out.Open;
    
        C.exit(TRUE)
    END program.
    
    Поддержку Linux хотелось бы сделать, но пока до этого руки не доходят.
  • akron1 wrote:Тогда "кроссплатформенный" код главного модуля будет выглядеть так:

    Code: Select all

    MODULE program;
    
    IMPORT C := Console, In, Out;
    
    BEGIN
        C.open;
    
        C.exit(TRUE)
    END program.
    
    Это вполне хороший вариант.
    Я просто думал, как бы так сделать, чтобы поменьше вызывать лишнего.
    akron1 wrote:Ну а финализацию куда всунуть?
    Если только неявно после выполнения основного кода

    Code: Select all

          IF Console.Initialized THEN
            Console.exit
          END;
    
    Например, у XDS(Oberon-2) есть такой код, где вызывается In.Open, но без Out.Open
    Spoiler:

    Code: Select all

    <*+ MAIN *> 
    MODULE ackermann;
    
    IMPORT Out, In;
    
    VAR p1, p2, count: LONGINT;
    
    PROCEDURE ack (m, n: LONGINT): LONGINT;
    BEGIN
      INC (count);
      IF m=0 THEN RETURN n+1 END;
      IF n=0 THEN RETURN ack (m-1, 1) END;
      RETURN ack (m-1, ack (m, n-1));
    END ack;
    
    BEGIN
      In.Open;
      count := 0;
      Out.String ("Ackermann Function Calculation"); Out.Ln;
      Out.String ("------------------------------"); Out.Ln;
      Out.Ln;
      Out.String ("Enter first  parameter (1..4): "); In.LongInt(p1);
      Out.String ("Enter second parameter (1..7): "); In.LongInt(p2);
      Out.Ln;
      Out.String ("Ackermann ("); Out.Int (p1, 0);
      Out.String (", "); Out.Int(p2, 0);
      Out.String ("): ");
      Out.Int (ack (p1, p2), 0);
      Out.String (" ("); Out.Int (count, 0);
      Out.String (" recursive calls)");
      Out.Ln;
    END ackermann.
    
    А есть вообще безо всяких Open
    Spoiler:

    Code: Select all

    <* MAIN+ *>
    MODULE GCreport; 
    
    IMPORT SYSTEM, oberonRTS, Out;
    
    TYPE Object = POINTER TO ObjDesc;
         ObjDesc = RECORD 
         END;
    
    VAR 
      global: Object;
      count: INTEGER;
    
    PROCEDURE Finalize(a: SYSTEM.PTR);
    BEGIN
      INC(count);
      Out.String("Garbage Collector: "); Out.Int(count,0); Out.Ln;
      global:=SYSTEM.VAL(Object,a);
      oberonRTS.InstallFinalizer(Finalize,global);
    END Finalize;
    
    PROCEDURE Init;
      VAR o: Object;
    BEGIN
      count:=0;
      NEW(o);
      oberonRTS.InstallFinalizer(Finalize,o);
      NEW(o);
      oberonRTS.InstallFinalizer(Finalize,o);
      global:=o;
    END Init;
    
    BEGIN
      Init;
      oberonRTS.Collect;
      oberonRTS.Collect;
      oberonRTS.Collect;
      oberonRTS.Collect;
    END GCreport.
    Значит, всё же это можно как-то организовать неявно.
    Ну при завершении программы как минимум.
  • 0CodErr wrote:
    akron1 wrote:Тогда "кроссплатформенный" код главного модуля будет выглядеть так:

    Code: Select all

    MODULE program;
    
    IMPORT C := Console, In, Out;
    
    BEGIN
        C.open;
    
        C.exit(TRUE)
    END program.
    
    Это вполне хороший вариант.
    Я просто думал, как бы так сделать, чтобы поменьше вызывать лишнего.
    Пока сделал так. Теперь можно не вызывать In.Open и Out.Open.
  • Я перестроил компилятор на генерацию машинного кода с формированием исполняемых файлов (PE и MENUET01). FASM больше не нужен. Генерация obj-библиотек пока не поддерживается. Размер машинного кода стал на 15% больше (сжатый на 5%), потому что компилятор пока генерирует длинные команды переходов там, где возможны короткие.

    20.11.2018
    Поддержка obj-библиотек восстановлена. Также сделал генерацию позиционно-независимого кода. Для KolibriOS это не нужно, но может быть для чего-нибудь пригодится.

    25.11.2018
    Короткие команды переходов, отключаемый рантайм контроль типов, индексов и указателей.