OberonCore

Библиотека  Wiki  Форум  BlackBox  Компоненты  Проекты
Текущее время: Понедельник, 24 Июнь, 2024 09:13

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 334 ]  На страницу Пред.  1 ... 13, 14, 15, 16, 17
Автор Сообщение
СообщениеДобавлено: Пятница, 08 Март, 2024 20:20 
Аватара пользователя

Зарегистрирован: Вторник, 28 Август, 2007 00:55
Сообщения: 522
Откуда: Украина, Днепропетровская обл.
Посмотрел ошибку. Также она присутствует в Ofront (voc) и в CPfront (МультиОберон).

Ofront:
Код:
static void Ex_Example (CHAR *b, LONGINT b__len, LONGINT b__len1)
{
   struct Example__1 _s;
   _s.b = (void*)b; _s.b__len = b__len; _s.b__len = b__len;

CPfront:
Код:
static void Ex_Example (CHAR *b, INTEGER b__len, INTEGER b__len1)
{
   struct Example__1 _s;
   __ENTER("Ex.Example");
   _s.b = (void*)b; _s.b__len = b__len; _s.b__len = b__len;
      <-- нужно _s.b__len = b__len; _s.b__len1 = b__len1;


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Пятница, 08 Март, 2024 21:33 
Аватара пользователя

Зарегистрирован: Вторник, 28 Август, 2007 00:55
Сообщения: 522
Откуда: Украина, Днепропетровская обл.
Починил. Спасибо за информацию.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Вторник, 12 Март, 2024 20:35 

Зарегистрирован: Вторник, 12 Март, 2024 20:31
Сообщения: 15
Здравствуйте, Олег!

Думаю перейти с содержащего ошибки и не поддерживаемого oo2c на Ofront+, но столкнулся с проблемой. Возможно ли каррирование в Ofront+?

Вот такая программа не проходит трансляцию в Офронте+:
Код:
MODULE test;
IMPORT Out;

TYPE f = PROCEDURE(b: INTEGER): INTEGER;

PROCEDURE Add(a: INTEGER): f;
        PROCEDURE F(b: INTEGER): INTEGER;
        BEGIN
                RETURN a + b
        END F;
BEGIN
        RETURN F
END Add;

BEGIN
        Out.Int(Add(16)(25),2);
        Out.Ln;
END test.

Транслятор выдаёт ошибку:
Код:
test.ob2  translating test
    13:1  err 73  procedure must have level 0

voc тоже отказывается компилировать, выдавая похожую ошибку:
Код:
test.Mod  Compiling test.

  12:   RETURN F
              ^
    pos   177  err 73  procedure must have level 0

  16:   Out.Int(Add(16)(25),2);
                     ^
    pos   210  err 113  incompatible assignment

Module compilation failed.

При этом oo2c компилирует без проблем, и программа работает, как задумано.
Единственное, что можно отметить, это предупреждение от линковщика:
Код:
/usr/bin/ld: warning: obj/test.o: requires executable stack (because the
.note.GNU-stack section is executable)

Это так и было задумано? Но почему? Ведь такое каррирование, как я
понимаю, разрешается описанием языка Оберон-2. Если так и задумано, то как
подобные задачи решают в Офронте+?


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Среда, 13 Март, 2024 14:22 

Зарегистрирован: Вторник, 12 Март, 2024 20:31
Сообщения: 15
olenellus писал(а):
Ведь такое каррирование, как я
понимаю, разрешается описанием языка Оберон-2.

Наверно, я неправ. Вот цитата:
The Programming Language Oberon-2 писал(а):
If a procedure P is assigned to a procedure variable of type T… P must not be declared local to another procedure, and neither can it be a standard procedure.

Как же мне теперь мою задачу решать?..


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Среда, 13 Март, 2024 20:11 
Аватара пользователя

Зарегистрирован: Вторник, 28 Август, 2007 00:55
Сообщения: 522
Откуда: Украина, Днепропетровская обл.
Похоже, что Вы пытаетесь вытащить вложенную процедуру в общее поле видимости. На самом деле внутренне вложенная процедура прикреплена к специальной структуре данных, которая заполняется родительской процедурой неявно, и через которую вложенная и родительская процедура обмениваются данными. И я не вижу простого способа сделать вложенную процедуру равноценной внешней, это противоречит самой логике её вложенности. Вложенная процедура это внутренняя процедура, она для этого таковой задумана. Нет возможности воспользоваться ею как внешней. Зато она имеет доступ к параметрам и переменным родительской процедуры (оставим пока за бортом извращения Оберона-07) как раз через эту внутреннюю структуру. Кстати, извращения в O7 как раз и вызваны желанием избавиться от этой внутренней структуры.

Да. Слово "каррирование" слышу вообще впервые, но абсолютно уверен, что Ваш код можно переписать при помощи обычной (не вложенной) процедуры.

Ну смотрите сами, здесь же явная неувязка:
Код:
PROCEDURE Add(a: INTEGER): f;
        PROCEDURE F(b: INTEGER): INTEGER;
        BEGIN
                RETURN a + b  <-- допустим, Вы передали процедуру F вовне; откуда она возьмёт значение a?
        END F;


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Среда, 13 Март, 2024 22:48 

Зарегистрирован: Вторник, 12 Март, 2024 20:31
Сообщения: 15
Хм. Тогда значит вопрос мой не по транслятору, а по общим принципам программирования, и его следует по-хорошему в другом месте задать. Интересно, что oo2c делает как раз то, что мне надо. Суть такая. Я написал модуль для численного интегрирования ОДУ методом Рунге-Кутты с намерением использовать его для всякого рода задач. Вот его интерфейс
Код:
MODULE RK;

TYPE
  State* = POINTER TO ARRAY OF LONGREAL;
  RHSElement* = PROCEDURE(input: State): LONGREAL;
  RightHandSide* = POINTER TO ARRAY OF RHSElement;


PROCEDURE UpdateRK4*(VAR state: State; RHS: RightHandSide; step: LONGREAL);
(* An application of the Runge-Kutta 4 method with time-step 'step'.  The
   array of state and of the right hand side functions must be defined in
   the calling application *)

PROCEDURE UpdateRKF45*(VAR state: State; RHS: RightHandSide; VAR step: LONGREAL; VAR oldStep: LONGREAL; rtol: LONGREAL; atol: LONGREAL);
(* An application of the Runge-Kutta-Fehlberg 45 method with the initial
   time-step guess 'step'.  The array of state and of the right hand side
   functions must be defined in the calling application.  Internally RK4 and
   RK5 are performed and the result is compared. If significantly different
   (w.r.t.  to the tolerance), 'step' is updated. The new 'step' estimate
   (for the next application) is returned alongside with the updated
   'state'. The actually used step during the 'state' update is returned in
   'oldStep'. 'rtol' is the relative error tolerance, 'atol' is the absolute
   error tolerance *)

END RK.

От конкретного приложения требуется определить вектор состояния и задать длину (тип State — это указатель на него) а также предоставить правые части динамических уравнений (тип RightHandSide — это указатель на компоненты векторного поля, каждая из них берёт (указатель на) вектор состояния и выдаёт действительное число — скорость изменения соответствующей координаты). Дальше модуль обсчитывает один шаг интегрирования с такими вводными. Я намеревался использовать модуль для задач самого широкого круга: от расчёта входа спускаемого аппарата в плотные слои атмосферы до расчёта кинетики взаимодействия олигонуклеотидов.

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

PROCEDURE dotBT(i: LONGINT; SunY: LONGREAL): RK.RHSElement;
    PROCEDURE ParametrizedFunction(composition: RK.State): LONGREAL;
    VAR X: Chemicals;
    BEGIN
        ComputeChemicals(X, composition);
        RETURN
        - kATon[i]*X.A*X.BT + kAToff[i]*X.ABT + kBTon[i]*X.B*X.T - kBToff[i]*X.BT
        + kEnz*SunY*X.BDE
    END ParametrizedFunction;
BEGIN
    RETURN ParametrizedFunction;
END dotBT;


В теле самого модуля далее присвоение производится следующим образом
Код:

VAR
    composition: RK.State;
    RHS: RK.RightHandSide;

RHS^[10] := dotBT(0,SunY);

где 0 и SunY — внешние параметры.

Короче, мне надо как-то сконструировать функцию типа RightHandSide (берущую указатель типа State и возвращающую LONGREAL) с использование внешних параметров. Как это правильно сделать в Обероне?


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Четверг, 14 Март, 2024 01:31 
Аватара пользователя

Зарегистрирован: Вторник, 28 Август, 2007 00:55
Сообщения: 522
Откуда: Украина, Днепропетровская обл.
Самое простое, что я предложу, это сделать процедуру ParametrizedFunction не внутренней и добавить ей параметров i: LONGINT; SunY: LONGREAL, которые сейчас передаются ей через родительскую процедуру.

Но вообще наверное тянет на объект. Завести запись с этими значениями, передавать параметром VAR эту запись в ParametrizedFunction.

Удивлён, что oo2c "делает как раз то, что Вам надо" — кабы это не очередной его баг ;)


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Вторник, 19 Март, 2024 02:34 

Зарегистрирован: Вторник, 12 Март, 2024 20:31
Сообщения: 15
Спасибо! Вы навели меня на возможное решение. Помучившись немного и прочитав пару соседних веток про функциональные переменные и объекты, реализовал-таки решение через обероновское ООП. Наконец, понял, как это вообще работает. До этого про ООП у меня были мифические представления.

Короче, теперь интерфейс выглядит так (в стиле oo2c):
Код:
MODULE RKrec;

TYPE
  State* = POINTER TO ARRAY OF LONGREAL;
  DynamicalSystem* = POINTER TO DynamicalSystemVariables;
  DynamicalSystemVariables* = RECORD
    (* May be extended to include external parameters *)
    state*: State;

    PROCEDURE (ds: DynamicalSystem) ComputeRHS*(result: State);
    (* Must be redefined by the target application, for now does nothing *)

    PROCEDURE (ds: DynamicalSystem) GenerateK(VAR k1: State; VAR k3: State; VAR k4: State; VAR k5: State; VAR k6: State; h: LONGREAL; generateK6: BOOLEAN);

    PROCEDURE (ds: DynamicalSystem) UpdateRK4K(k1: State; k3: State; k4: State; k5: State; step: LONGREAL);

    PROCEDURE (ds: DynamicalSystem) UpdateRK4*(step: LONGREAL);
    (* An application of the Runge-Kutta 4 method with time-step 'step'.
       The array of state and of the right hand side functions must be
       defined in the calling application *)

    PROCEDURE (ds: DynamicalSystem) UpdateRKF45*(VAR step: LONGREAL; VAR oldStep: LONGREAL; rtol: LONGREAL; atol: LONGREAL);
    (* An application of the Runge-Kutta-Fehlberg 45 method with the initial
       time-step guess 'step'.  The array of state and of the right hand
       side functions must be defined in the calling application.
       Internally RK4 and RK5 are performed and the result is compared. If
       significantly different (w.r.t.  to the tolerance), 'step' is
       updated. The new 'step' estimate (for the next application) is
       returned alongside with the updated 'state'. The actually used step
       during the 'state' update is returned in 'oldStep'. 'rtol' is the
       relative error tolerance, 'atol' is the absolute error tolerance *)
  END;

END RKrec.

где все процедуры теперь связаны с соответствующими записями, а вычисление правых частей — пустая процедура. В целевой же программе я расширяю тип DynamicalSystem путём добавления полей с нужными параметрами и объявляю новый тип указателя на такие переменные (т. е. сужаю класс, тут забавная дуальность: расширение записи приводит к сужению класса) и переопределяю вычисление правых частей сообразно задаче:
Код:
MODULE test2;

IMPORT RK := RKrec, Out;

CONST
    step = 1.0;
    parameter = 0.5;

TYPE
    DynamicalSystem = POINTER TO DSVars;
    DSVars = RECORD (RK.DynamicalSystemVariables)
        parameter: LONGREAL;
    END;

VAR
    ds: DynamicalSystem;

PROCEDURE (ds: DynamicalSystem) ComputeRHS*(result: RK.State);
VAR i: LONGINT;
BEGIN
    FOR i := 0 TO LEN(ds.state^)-1 DO;
        result[i] := ds.state[i]*ds.parameter;
    END;
END ComputeRHS;

BEGIN
    NEW(ds); NEW(ds.state,2);
    ds.parameter := parameter;
    ds.state[0] := 1.0;
    ds.state[1] := 2.0;
    Out.LongReal(ds.state[0],5,0); Out.Ln;
    Out.LongReal(ds.state[1],5,0); Out.Ln; Out.Ln;
    ds.UpdateRK4(step);
    Out.LongReal(ds.state[0],5,0); Out.Ln;
    Out.LongReal(ds.state[1],5,0); Out.Ln; Out.Ln;
END test2.

и всё работает. oo2c зачем-то заставил меня экспортировать переопределённую процедуру ComputeRHS, но, вообще-то, в Обероне-2 это не требуется (ofronto-подобные компиляторы нормально работают и без этого). Так вот ты какое, ООП.

Шёл я к этому неделю. Спасибо за наводку. Раньше не имел дел с ООП. Сначала утонул в чужеродной терминологии. Потом открыл книжку Object-Oriented Programming in Oberon-2, и стало более-менее понятно.

Кстати, вернёмся к офронту+. Мне кажется очень удобным то, что утилита oo2c для чтения интерфейсов показывает комментарии (но только особые комментарии — начинающиеся с (** ). showdef этого не делает. Например, в случае выше пришлось бы лезть в исходный текст, чтобы понять, что требуется от целевой программы.

И ещё один вопрос. А в Обероне-2 в принципе запрещено присваивание переменных типа массива или только не реализовано (что в oo2c, что в офронто-подобных)? Вроде бы, из описание языка это напрямую не следует. В Обероне-07 присваивание массивов разрешено (реализовано, например, в obnc), правда, там и массивы все с заранее известной длиной. А то приходится городить специальную процедуру для копирования.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Среда, 20 Март, 2024 18:07 
Аватара пользователя

Зарегистрирован: Вторник, 28 Август, 2007 00:55
Сообщения: 522
Откуда: Украина, Днепропетровская обл.
Рад Вашим успехам! :)

olenellus писал(а):
Кстати, вернёмся к офронту+. Мне кажется очень удобным то, что утилита oo2c для чтения интерфейсов показывает комментарии (но только особые комментарии — начинающиеся с (** ). showdef этого не делает. Например, в случае выше пришлось бы лезть в исходный текст, чтобы понять, что требуется от целевой программы.
Я всецело с Вами согласен. Думал когда-то о таком функционале. В ETH Oberon есть утилита Watson, которая делает именно это. Тут, по-видимому, два возможных подхода: или пихать такие "экспортированные коммментарии" в символьные файлы, или же давать утилите доступ к исходнику. По крайней мере, чтобы она однозначно находила исходный модуль по символьнику. Что не всегда возможно, поскольку имя файла модуля может отличаться от имени модуля.

Мне не нравятся оба подхода. Я взялся было портировать утилиту Watson (там в репозитории болтается), но не закончил. А так - функционал нужный, ещё думаю над этим. Любая помощь приветствуется.

olenellus писал(а):
И ещё один вопрос. А в Обероне-2 в принципе запрещено присваивание переменных типа массива или только не реализовано (что в oo2c, что в офронто-подобных)?
Да всё там есть, смотрите:


Вложения:
CopyArr.png
CopyArr.png [ 53.8 КБ | Просмотров: 4354 ]
Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Четверг, 28 Март, 2024 03:00 

Зарегистрирован: Вторник, 12 Март, 2024 20:31
Сообщения: 15
Я тут ещё поковырял A2 на предмет среды запуска своих программ. И вот, что хочу доложить. Обсчёт вышеприведённого модуля test с 2000000 итерациями ds.UpdateRK4(step) (ну и с другим значением параметра, чтобы за допустимые пределы не вылетело) занял такое время:
  • A2: 11 с
  • voc: 7,5 c
  • Ofront+: 1,5 с
  • oo2c: 1,5 с
А я думал, Ofront+ будет на ровне с voc, а он, оказывается, в спину дышит oo2c. Намучился я, правда, с компиляцией и линковкой без установки офронта+ в систему. Для меня сишные телодвижения с линковкой непривычны.

A2 запускал в режиме интерпретатора командной строки, без графической оболочки. На A2 смотрел, задумавшись, как бы лучше использовать 4 процессора с 26 ядрами каждый у нас на рабочем сервере.

А ещё не знаю пока, как на этом сервере собрать офронт+. Там старая Убунту, и версия libc не подходит. Жаль. Быстро работает, однако.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Четверг, 28 Март, 2024 15:23 
Аватара пользователя

Зарегистрирован: Вторник, 28 Август, 2007 00:55
Сообщения: 522
Откуда: Украина, Днепропетровская обл.
olenellus писал(а):
  • voc: 7,5 c
  • Ofront+: 1,5 с
Скорее всего, тут дело не в Ofront'е+, а в опциях GCC -O0-3 -Os, с которыми собирается код. voc, вероятно, и сам собран с -O0, и GCC вызывает тоже с -O0 (может быть с -O1). Разработчики трансляторов Оберона в Си почему-то боятся сишной оптимизации. Вероятно, потому, что она может добавить нестабильности. Что до меня, я сознательно использую при работе с Ofront+ GCC с оптимизацией даже не по скорости, а по размеру -Os (скорость - побочный эффект), что в своё время позволило найти проблемы в сборщике мусора (при переводе его на 64-битность), которые могли остаться в voc. Но на 100% ничего утверждать не буду, т.к. voc не пользуюсь.

olenellus писал(а):
Для меня сишные телодвижения с линковкой непривычны.
Прошу прощения. Но так больше гибкости при вызове разных сишных компиляторов.

olenellus писал(а):
А ещё не знаю пока, как на этом сервере собрать офронт+. Там старая Убунту, и версия libc не подходит. Жаль. Быстро работает, однако.
Есть ли возможность обновить там Убунту?

Ofront+ должен собираться и со старой libc. А в чём конкретно трудности?

Смотрите. Если на старой Убунту не запускается бинарь Ofront'а+, собранный для более новой libc, делайте так:

Скопируйте туда дистриб Ofront'а+. Переходите в нужную папочку (Target/Linux_amd64 если линукс 64-битный и Target/Linux_i386 если 32-битный).

Идёте на https://github.com/Oleg-N-Cher/OfrontPlus-bootstrap

Для 64-битного линукса нас интересует папочка unix-88, для 32-битного unix-44.

Всё там конечно свалено в одну кучу, но для упрощения из папочки unix* нужной разрядности копируете все файлы *.c и *.oh в Obj и их же в Lib/Obj

Потом запускаете Lib/Bin/cc и Bin/cc

Всё собрано именно для вашей версии libc. Дальше Ofront+ сможет пересобирать сам себя.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Четверг, 28 Март, 2024 15:53 

Зарегистрирован: Вторник, 12 Март, 2024 20:31
Сообщения: 15
Спасибо! Попробую совладать.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Четверг, 23 Май, 2024 13:53 

Зарегистрирован: Вторник, 12 Март, 2024 20:31
Сообщения: 15
Забыл поблагодарить. Большое спасибо, всё работает!

Вообще, офронт+ оказался очень удобным компилятором, особенно после настройки прилагаемого omake и написания небольшого скрипта для организации файлов где надо и как надо. И при этом всё быстро летает. И прилагаемые библиотеки достаточно богаты (я активно пользуюсь не совсем обероновской aria). Удалось (правда, не напрямую, а немного через одно место, через простой дополнительный сишный файл) прицепиться к библиотеке для моделирования сворачивания РНК ViennaRNA. Всё работает! Активно делаю науку.

Ещё раз спасибо!


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: Четверг, 23 Май, 2024 14:26 
Аватара пользователя

Зарегистрирован: Вторник, 28 Август, 2007 00:55
Сообщения: 522
Откуда: Украина, Днепропетровская обл.
Очень рад, что Вам нравится Ofront+
Мы старались :D

Кстати, там некоторые вещи по низкоуровневым биндингам не вполне очевидны. Больше можно подсмотреть в подсистемах к XDev: Pdp11Dev NesDev SmdDev MsxDev K580Dev DosDev GBDev UkncDev WinDev ZXDev

Как видите, средств в биндингах вполне достаточно, чтобы прицепиться к настолько разнообразным платформам. Кое-где через доп. Си-файлы, кое-где и просто через Оберон-интерфейсы.

Также есть Телеграм-группа по поддержке Ofront+


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 334 ]  На страницу Пред.  1 ... 13, 14, 15, 16, 17

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 4


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Вся информация, размещаемая участниками на конференции (тексты сообщений, вложения и пр.) © 2005-2024, участники конференции «OberonCore», если специально не оговорено иное.
Администрация не несет ответственности за мнения, стиль и достоверность высказываний участников, равно как и за безопасность материалов, предоставляемых участниками во вложениях.
Без разрешения участников и ссылки на конференцию «OberonCore» любое воспроизведение и/или копирование высказываний полностью и/или по частям запрещено.
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB