OberonCore

Библиотека  Wiki  Форум  BlackBox  Компоненты  Проекты
Текущее время: Понедельник, 11 Август, 2025 13:14

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




Начать новую тему Ответить на тему  [ Сообщений: 332 ]  На страницу Пред.  1 ... 3, 4, 5, 6, 7, 8, 9 ... 17  След.
Автор Сообщение
 Заголовок сообщения: Re: Oberon/Ur
СообщениеДобавлено: Воскресенье, 04 Август, 2024 07:16 

Зарегистрирован: Воскресенье, 25 Декабрь, 2022 23:14
Сообщения: 1562
кстати, не понимаю, почему у `SYSTEM.PUT()` именно такой порядок аргументов — (куда, что). у `SYSTEM.MOVE()`, например, (откуда, куда, сколько). у `COPY()` — (откуда, куда). по-моему, или трусы, или крестик. так что у себя для `PUT()` сделал (что, куда). у `SYSTEM.FILLCHAR()` тоже: (чем, где, сколько).


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Oberon/Ur
СообщениеДобавлено: Воскресенье, 04 Август, 2024 17:14 
Аватара пользователя

Зарегистрирован: Вторник, 19 Сентябрь, 2006 21:54
Сообщения: 2463
Откуда: Россия, Томск
Это чтобы визуально порядок сохранить как у присвоения:
SYSTEM.PUT(куда, что);
куда := что;


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Oberon/Ur
СообщениеДобавлено: Воскресенье, 04 Август, 2024 17:31 

Зарегистрирован: Воскресенье, 25 Декабрь, 2022 23:14
Сообщения: 1562
это было бы логично, если бы все остальные тоже такой порядок сохраняли. вот в сишечке так и есть: там везде `dest, src`. а у нас имеем необходимость помнить, где рыбу заворачивали. почему одна процедура «как присваивание», а другая (стандартная, ваще без систем!) — COPY — наоборот? каким образом предлагается запомнить, где какой порядок? я лично так и не смог, всегда в CP в `PUT()` писал как в `COPY()`, и каждый раз жутко матерился.

да ляп это просто, ящитаю. не надо ему никаких обоснований искать. нечаянно сделали и забыли, потому что редко используется. а потом уже править смысла не было — кода понаписали.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Oberon/Ur
СообщениеДобавлено: Воскресенье, 04 Август, 2024 17:58 

Зарегистрирован: Воскресенье, 25 Декабрь, 2022 23:14
Сообщения: 1562
и больше блогов богу блогов.

во-первых, Oberon/Ur всегда зануляет `OUT`. собственно, локальные переменные тоже всегда. да, так в спецификации: «все локалы всегда инициализируются положительными нулями или NIL». не вижу ни одной причины это не делать, зато вижу много причин делать.

во-вторых, дельфийские строки реально удобные. им ещё можно присваивать `ARRAY OF CHAR` — оттуда автоматически достанут 0-terminated. и обратно можно.

конкатенация строк через `~` правильней, чем через `+`. обсуждению не подлежит. ;-)

борюсь с искушением сделать `LEN(var) := expr;` для динамических массивов и строк. это те самые «красивые умности», которых надо в дизайне языка избегать. но как прикольно же выглядит!

а. я говорил, что сигилы в O/Ur обязательны? `@v` для `VAR`, `^v` для `OUT`.

размышляю, не забанить ли доступ к UPSCOPE локалам во вложеных процедурах. как в оберон07. ратионале: в O/Ur всё равно все апскопы надо вручную объявлять в секции `VAR`. а раз так — то почему бы не объявлять их явно в сигнатуре, и явно же не передавать? из преимуществ — упрощение кодогена; отбивание охоты делать вложеные процедуры, которые дёргают кучу апскопов (это плохой код).
против: менее удобно выделять в отдельные процедуры какие-то сложные проверки в `IF`.
временное решение: пока забаню. если пойму, что жить без этого очень плохо — разбаню обратно и сделаю.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Oberon/Ur
СообщениеДобавлено: Воскресенье, 04 Август, 2024 18:05 

Зарегистрирован: Воскресенье, 25 Декабрь, 2022 23:14
Сообщения: 1562
и в дополнение к `PUT()`.

`:=` в оберонах — это не «assign», а «becomes». это вообще вот этот символ: «←». которого, к сожалению, в ascii нет, а `<-` не парзится однозначно без семантической информации. соответственно «ptr-to-smth becomes value» читается странно и неоднозначно. по той же причине не читаются извращения типа `+:=` (или `:+=`, один фиг уродец).

отсюда же, кстати, `=` вместо `:=` в объявлении констант. потому что там мы как раз объявляем тождества.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Oberon/Ur
СообщениеДобавлено: Воскресенье, 04 Август, 2024 18:15 

Зарегистрирован: Воскресенье, 25 Декабрь, 2022 23:14
Сообщения: 1562
и ещё. раздумываю, не сделать ли опциональные секции `IN` и `OUT`, в которых можно проверять инварианты. как-то так:
Код:
PROCEDURE Proc (a, b: INTEGER): INTEGER;
IN
  ASSERT(a > 0);
  ASSERT(b # 0);
OUT
  ASSERT(res > 0);
VAR res: INTEGER;
BEGIN
  чотатам
  RETURN res;
END Proc;

нувыпонели.

так-то это, конечно, можно и прямо в теле процедуры писать. но отдельно оно удобно для автоматической генерации документации. да и для читателя кода тоже удобней, мне кажется.

прибить это гвоздями сразу после PROCEDURE, чтобы видно. компилятор всё равно многопроходный, позволяет таким вот образом к `res` обращаться.

p.s.: или вообще так:
Код:
PROCEDURE Proc (a, b: INTEGER): INTEGER;
IN
  ASSERT(a > 0);
  ASSERT(b # 0);
OUT
  ASSERT(RETURN > 0);
BEGIN
  чотатам
END Proc;

и пофигу, что там ретурнят.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Oberon/Ur
СообщениеДобавлено: Понедельник, 05 Август, 2024 00:07 

Зарегистрирован: Воскресенье, 25 Декабрь, 2022 23:14
Сообщения: 1562
поскольку у меня, фактически, всё нужное есть уже — потихоньку переношу буилтины из крестоядра в `System:Kernel`. в смысле — вместо звать регистрированые сишные функции, компилятор делает автоимпорт Kernel, и вставляет обычные `NodeCall`. в идеале туда всё уехать должно.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Oberon/Ur
СообщениеДобавлено: Понедельник, 05 Август, 2024 04:56 

Зарегистрирован: Воскресенье, 25 Декабрь, 2022 23:14
Сообщения: 1562
красота!
Код:
PROCEDURE IntrinsicDStrUnique* (VAR ss: STRING; allocEmpty: BOOLEAN);
VAR
  str, newstr: DynStringPtr;
  tvar, sadr: S.ADDRESS;
  newcap: INTEGER;
BEGIN
  tvar := S.ADR(ss);
  sadr := S.GET(S.ADDRESS, tvar);
  IF sadr # NIL THEN
    str := S.CAST(DynStringPtr, sadr);
    IF str.refc # 1 THEN
      newcap := CalcStrCapacity(str.length);

      sadr := AllocMem(S.CAST(S.USIZE, SIZE(DynString)));
      ASSERT(sadr # NIL, "out of memory for string");
      newstr := S.CAST(DynStringPtr, sadr);

      newstr.data := AllocMemRaw(S.CAST(S.USIZE, newcap));
      IF newstr.data = NIL THEN
        FreeMem(sadr);
        ASSERT(newstr.data # NIL, "out of memory for string data");
      END IF
      DEC[unchecked](str.refc);
      S.PUT(sadr, tvar);

      newstr.refc := 1;
      newstr.length := str.length;
      newstr.capacity := newcap;

      (* copy with final zero byte *)
      S.MOVE(str.data, newstr.data, str.length + 1);
    END IF
  ELSIF allocEmpty THEN
    sadr := AllocMem(S.CAST(S.USIZE, SIZE(DynString)));
    ASSERT(sadr # NIL, "out of memory for string");
    str := S.CAST(DynStringPtr, sadr);

    newcap := CalcStrCapacity(0);
    str.data := AllocMemRaw(S.CAST(S.USIZE, newcap));
    IF str.data = NIL THEN
      FreeMem(sadr);
      ASSERT(str.data # NIL, "out of memory for string data");
    END IF
    S.PUT(sadr, tvar);

    str.refc := 1;
    str.length := 0;
    str.capacity := newcap;

    S.PUT(0X, str.data);
  END IF
END IntrinsicDStrUnique;

и компилируется, и работает, и компилятор вставляет вызовы этой штуки. и других разных штук для строк. моя прелесть!


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Oberon/Ur
СообщениеДобавлено: Понедельник, 05 Август, 2024 23:37 

Зарегистрирован: Воскресенье, 25 Декабрь, 2022 23:14
Сообщения: 1562
сделал, наконец, строитель typeid-ов. а то все использовали указатель на крестокласс вместо этого. фи таким быть. можно потихоньку начинать пилить гц. и `IS` наконец сделать O(1).

надо ещё запилить распаковщик тайпидов обратно в крестоклассы, чтобы из скомпиленых модулей типы восстанавливать. понадобится потом для динамической докомпиляции модулей.

вообще, можно в Nanojit добавить генерацию фиксапов, конечно. помечать инструкции с адресами как `needFixup`, и потом это спокойно править. единственная проблема — с ARM-бэкэндом. у Nanojit довольно забавно сделано: там память под код выделяется по одной странице, и в начале страницы лежит constant pool. ну, чтобы доставать его короткими инструкциями, как я понял из комментариев. это, видимо, важно для тумбочек, или что-то типа того.

но об этом я подумаю как-нибудь очень позже. однако придётся: раз уж я не тестовый компилятор делаю, а полноценный — то придётся и код на диск писать.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Oberon/Ur
СообщениеДобавлено: Вторник, 06 Август, 2024 20:58 

Зарегистрирован: Воскресенье, 25 Декабрь, 2022 23:14
Сообщения: 1562
ура, практически milestone: вынес крестобуилтины в `System:Kernel`. а это в том числе и скан разных типов на предмет строк, чтобы сделать строкам `decref()` — такие вызовы генерятся на выходе из процедуры, если в ней строковые переменные есть.

то есть, это значит, что во-первых, typedef-ы строятся правильно, а во-вторых, ядро их правильно обрабатывает.

теперь надо добавить стековые карты, и можно пилить GC.

для трапов и ассертов, кстати, тоже вызывают `System:Kernel.IntrinsicTrap()`, так что ядро имеет практически полный контроль теперь. кроме обработчика сигналов — сигналы пока не ловятся. для чисто обероновского кода оно не очень важно, потому что там везде явные проверки на NIL, на деление на ноль, такое вот. но надо, конечно, сигналы сделать.

выглядит, само собой, страшно:
Код:
TYPE
  TypeIdRecPtr = POINTER TO RECORD [untagged, align1]
    inhLevelAndFlags: INTEGER; (* low word is inhlevel, high word is flags *)
    vmtSize: INTEGER; (* in bytes *)
    byteSize: INTEGER;
    recNameOfs: INTEGER;
      (* yes, memory waste; but it is easier this way; also, align data to 8 bytes) *)
    inhTable: ARRAY MaxInhLevel OF ADDR;
    fieldList: ADDR;
    methodList: ADDR;
    strmapptr: ADDR;
    ptrmapptr: ADDR;
    finalizeProcAddr: ADDR;
    (* VMT table follows *)
    vmt: ADDR;
  END;

  TypeIdArrPtr = POINTER TO RECORD [untagged, align1]
    baseTypeId: ADDR;
    dimCount: INTEGER;
    flags: SET;
    flatSize: INTEGER; (* `-1` means dynamic array *)
    dims: ARRAY MaxDims + 1 OF INTEGER;
  END;

PROCEDURE IntrinsicArrayDecRef* [nonilchecks] (typid: ADDR; flatSize: INTEGER; aptr: ADDR);
VAR
  btyid: TypeIdRecPtr;
  barr: TypeIdArrPtr;
  base, map, mapOrig: ADDR;
  ofs, aflat: INTEGER;
  bsz: USIZE;
BEGIN ASSERT(flatSize >= 0);
  IF flatSize = 0 THEN RETURN; END IF (* just in case *)

  IF typid = ktypeIdString THEN
    (* just a string *)
    REPEAT
      IntrinsicDStrDecRef(aptr);
      INC(aptr, PtrSize);
      DEC[unchecked](flatSize);
    UNTIL flatSize = 0;
    RETURN;
  END IF

  (* it should not be a pointer *)
  IF (typid < 4096) OR ODD(typid) THEN RETURN; END IF

  IF typid MOD 4 = 0 THEN
    btyid := S.CAST(TypeIdRecPtr, typid);
    (* record *)
    bsz := S.CAST(USIZE, btyid.byteSize);
    IF bsz = 0 THEN RETURN; END IF
    mapOrig := btyid.strmapptr;
    IF mapOrig = NIL THEN RETURN; END IF (* just in case *)
    ofs := S.GET(INTEGER, mapOrig);
    IF ofs = -1 THEN RETURN; END IF (* just in case *)
    REPEAT
      map := mapOrig;
      ofs := S.GET(INTEGER, map);
      REPEAT
        INC(map, SIZE(INTEGER));
        IntrinsicDStrDecRef(aptr + S.CAST(S.PTRDIFF, ofs));
        ofs := S.GET(INTEGER, map);
      UNTIL ofs = -1;
      INC(aptr, bsz);
      DEC[unchecked](flatSize);
    UNTIL flatSize = 0;
  ELSE
    (* array *)
    barr := S.CAST(TypeIdArrPtr, typid - 2);
    aflat := barr.flatSize;
    ASSERT(aflat >= 0);
    IF aflat = 0 THEN RETURN; END IF
    (* get base type *)
    base := barr.baseTypeId;
    (* check if we have something to do at all *)
    IF base # ktypeIdString THEN
      (* it should not be a pointer or an array *)
      IF (base < 4096) OR ODD(base) THEN RETURN; END IF
      (* actually, array should not end up here *)
      ASSERT(base MOD 4 = 0);
      (* check if our record has `strmap` at all *)
      btyid := S.CAST(TypeIdRecPtr, base);
      map := btyid.strmapptr;
      IF map = NIL THEN RETURN; END IF
      ofs := S.GET(INTEGER, map);
      IF ofs = -1 THEN RETURN; END IF (* just in case *)
      bsz := S.CAST(USIZE, btyid.byteSize);
      ASSERT(bsz # 0);
    ELSE
      bsz := PtrSize;
    END IF
    (* ok, we need to finalize something *)
    bsz := bsz * S.CAST(USIZE, aflat);
    REPEAT
      IntrinsicArrayDecRef(base, aflat, aptr);
      INC(aptr, bsz);
      DEC[unchecked](flatSize);
    UNTIL flatSize = 0;
  END IF
END IntrinsicArrayDecRef;

но камон, это системный код, он всегда страшный будет.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Oberon/Ur
СообщениеДобавлено: Среда, 07 Август, 2024 20:53 

Зарегистрирован: Воскресенье, 25 Декабрь, 2022 23:14
Сообщения: 1562
сижу и думаю, что, по ходу, проще всего переделать typeinfo под формат ящика, да тупо спереть memory manager оттуда. не, я могу и свой написать, конечно, но зачем? тем более в LC он лучше ваниллы, умеет лениво возвращать память системе, и я даже частично документировал внутренности (очень частично). или всё-таки сесть и новый написать…

опять конфликт интересов: и рабочую систему побыстрей охота, и сделать свой memory manager, быстрее-выше-сильнее. в BBCB, в общем-то, довольно дубовый аллокатор, его сильно улучшить можно по многим направлениям. вопрос только в нужности этих улучшений.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Oberon/Ur
СообщениеДобавлено: Четверг, 08 Август, 2024 19:42 

Зарегистрирован: Воскресенье, 25 Декабрь, 2022 23:14
Сообщения: 1562
кстати, а не сделать ли именованые аргументы? оно, конечно, мастерами-собаководами рекомендуется так:
Код:
CONST
  twistAndTurn = TRUE;
  standStill = FALSE;

PROCEDURE Dance (…; assMovement: BOOLEAN);

Dance(…, standStill);

но отчего бы не разрешить вот такое:
Код:
PROCEDURE Dance (…; assMovement: BOOLEAN);

Dance(…, assMovement:FALSE);

константы лучше, конечно, но иногда адово лень их объявлять.

на самом деле нужны таки enum'ы в виде EMPTY RECORDs, как я тут где-то писал. я их ещё не сделал. но и разрешить именованые аргументы — какая проблема? тогда и порядок аргументов может быть произвольный (но только если ВСЕ именованые). я как раз специально на этот случай сразу сделал специальную ноду `NodeArg`. в которой пока только одинокая `NodeExpr` лежит.

конечно, это привязывает код к именам аргументов процедур — но как по мне, то это нормально. по ходу, даже небольшая дополнительная защита. в идеале бы сделать имена аргументов обязательными, но такого садизма я сам не выдержу.

кстати, нужен INCLUDE. потому что я очень не люблю невнятные файлы в сотни килобайт размером. вот те же AST-ноды. технически они все принадлежат одному модулю. делать их все ABSTRACT, потом фабрику с директорией для каждой, потом пилить реализации в других модулях — это чисто дрочево ради дрочева. которое даже идеей делать разные бэкэнды не валидировать, потому что проще подменить high-level Nanojit API на генерацию не LIR, а чего-нибудь другого.

так вот. крестокод у меня побит примерно на десяток файлов реализации (и надо бы ещё поделить немного). если пытаться потом переписать компилятор на Oberon/Ur, то я лопну от отвращения, объединяя всё в один. поэтому нужен какой-то вариант INCLUDE.

или просто придумать схему именования дополнительных файлов, которые компилятор автоматически загрузит. ему-то порядок по барабану, лишь бы после IMPORT и до финального BEGIN. что-то типа: "ModName.inc.*.mod", например. так даже удобней будет.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Oberon/Ur
СообщениеДобавлено: Четверг, 08 Август, 2024 22:16 

Зарегистрирован: Воскресенье, 25 Декабрь, 2022 23:14
Сообщения: 1562
в общем, пока сделал `INCLUDE "filename";` в top-level. а чтобы не злоупотреблять, пытаясь какую-то макромагию сочинить.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Oberon/Ur
СообщениеДобавлено: Пятница, 09 Август, 2024 01:09 

Зарегистрирован: Воскресенье, 25 Декабрь, 2022 23:14
Сообщения: 1562
пилю пока простейший рекурсивный GC, чо там. лишь бы заработало. а уж потом этих… как их там, чертей… шноров всяких. а то сложно сейчас всё сразу отлаживать, лопну.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Oberon/Ur
СообщениеДобавлено: Пятница, 09 Август, 2024 09:45 

Зарегистрирован: Воскресенье, 25 Декабрь, 2022 23:14
Сообщения: 1562
частичный GC частично заработал. частичный — потому что не сделал decref для строк в освобождаемых блоках ещё. ну, забыл один цикл, бывает.

пока что дубовый-раздубовый, с рекурсивными пометками, и память системе не возвращает. и ещё много чего не делает, что LC умеет. но это всё неважно, это всё потом допишется. главное — оно долго крутилось в цикле с `NEW()`, причём в процедуре, вызваной из процедуры, и в каждой был `NEW()`. то есть, сканер работает, карты указателей для процедур ведутся верно.

стоимость процедурных карт — примерно пять команд на входе, две на выходе. они, конечно, активно пишут в память, но в одно и то же место (не считая стека), так что должны стоить недорого. собственно, я сделал генерацию карт для всех процедур, и проверил любимый «эксперимент» — замедление было на какие-то сотни мсек (из 11 секунд). приемлемо. precise GC того стоит, я считаю. к тому же карты трекаются только для процедур, в которых есть строковые локалы или локалы-указатели.

теперь надо будет перепроверить код, потом сделать нерекурсивные пометки.

единственное, что нельзя делать — это использовать сишные `setjmp()`/`longjmp()`. но это нигде нельзя, где есть механики исключений, например. в шинде надо будет как-то SEH нейтрализовать, но пока мне об этом думать лень.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Oberon/Ur
СообщениеДобавлено: Пятница, 09 Август, 2024 10:18 

Зарегистрирован: Воскресенье, 25 Декабрь, 2022 23:14
Сообщения: 1562
кстати. а я ведь могу даже compacting GC сделать потом. у меня ж точные карты указателей есть — бери да чини. и всякие другие эксперименты.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Oberon/Ur
СообщениеДобавлено: Пятница, 09 Август, 2024 22:14 
Аватара пользователя

Зарегистрирован: Вторник, 19 Сентябрь, 2006 21:54
Сообщения: 2463
Откуда: Россия, Томск
arisu писал(а):
это было бы логично, если бы все остальные тоже такой порядок сохраняли. вот в сишечке так и есть: там везде `dest, src`. а у нас имеем необходимость помнить, где рыбу заворачивали. почему одна процедура «как присваивание», а другая (стандартная, ваще без систем!) — COPY — наоборот? каким образом предлагается запомнить, где какой порядок?

Это просто объясняется: плохой дизайн.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Oberon/Ur
СообщениеДобавлено: Пятница, 09 Август, 2024 22:16 
Аватара пользователя

Зарегистрирован: Вторник, 19 Сентябрь, 2006 21:54
Сообщения: 2463
Откуда: Россия, Томск
arisu писал(а):
конкатенация строк через `~` правильней, чем через `+`. обсуждению не подлежит. ;-)
Через `&` ещё правильней.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Oberon/Ur
СообщениеДобавлено: Пятница, 09 Август, 2024 22:41 

Зарегистрирован: Воскресенье, 25 Декабрь, 2022 23:14
Сообщения: 1562
Александр Ильин писал(а):
arisu писал(а):
конкатенация строк через `~` правильней, чем через `+`. обсуждению не подлежит. ;-)
Через `&` ещё правильней.
теоретически да. а практически нет. причины против две. первая: бинарного `~` не существует, поэтому никакая операция не нагружается двумя разными действиями. вторая: да пофигу, я в дишечке так привык.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Oberon/Ur
СообщениеДобавлено: Пятница, 09 Август, 2024 23:02 

Зарегистрирован: Воскресенье, 25 Декабрь, 2022 23:14
Сообщения: 1562
Александр Ильин писал(а):
Это просто объясняется: плохой дизайн.
вот я его и выправил. в других местах, может, поломал — а тут выправил. пусть единообразно будет. запоминаем простые правила: `dest` всегда после `src`, `len` всегда после них. no exceptions. `FILLCHAR()` получился не совместимый ни с сишечкой, ни с паскалем, лол.


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 332 ]  На страницу Пред.  1 ... 3, 4, 5, 6, 7, 8, 9 ... 17  След.

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


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

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


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

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