OberonCore
https://forum.oberoncore.ru/

Что за untagged магия?
https://forum.oberoncore.ru/viewtopic.php?f=29&t=6636
Страница 1 из 1

Автор:  adimetrius [ Пятница, 10 Июль, 2020 00:44 ]
Заголовок сообщения:  Что за untagged магия?

Коллеги, почему работает вот это:

VAR s: POINTER TO ARRAY [untagged] OF CHAR;
t: POINTER TO ARRAY OF CHAR;
s := "Почему это работает?!"';
s := t^; (* ничуть не легче *)

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

Автор:  Oleg N. Cher [ Пятница, 10 Июль, 2020 08:10 ]
Заголовок сообщения:  Re: Что за untagged магия?

Просто для удобства и более чистого синтаксиса в КП разрешается опускать ^

Так что это операция "копирование строк по указателю".

Код:
VAR s: POINTER TO ARRAY [untagged] OF CHAR;
t: POINTER TO ARRAY OF CHAR;
s := "Почему это работает?!"; (* Копирование литерала-строки в буфер s *)
s := t^; (* Копирование строки по указателю t в буфер s *)

В данном случае это опасные присваивания — ведь размер буфера s может быть неизвестен, длина его нигде не хранится, ибо [untagged] для массива это тег, обозначающий, что это не Оберон-массив с хранимой длиной, а просто указатель на низкоуровневый буфер в памяти (в духе строк в Си).

Автор:  Oleg N. Cher [ Пятница, 10 Июль, 2020 08:43 ]
Заголовок сообщения:  Re: Что за untagged магия?

Кстати, всё обстоит ещё даже интереснее, чем я думал. Посмотрел, что нагенерит CPfront:

Код:
/*  CPfront 1.0 -48 */
#include "SYSTEM.h"

static CHAR *TestStr_s;
static struct CHAR_ARRAY *TestStr_t;


export void TestStr__body()
{

   TestStr_s = ((CHAR[]){1055, 1086, 1095, 1077, 1084, 1091, 32, 1101, 1090, 1086, 32, 1088, 1072, 1073, \
1086, 1090, 1072, 1077, 1090, 63, 33, 0});
   TestStr_s = TestStr_t->data;

}

Получается, что это операция не копирования, а получения опасного указателя на сырые данные в памяти. Наверное в BlackBox она реализована так же.

Автор:  Oleg N. Cher [ Пятница, 10 Июль, 2020 08:56 ]
Заголовок сообщения:  Re: Что за untagged магия?

Кстати, Дмитрий Дагаев. CPfront при описании безтегового массива не отлавливает наличие импорта SYSTEM. Как с этим в МультиОбероне? Проверьте, пожалуйста.

Изображение

Правда, не знаю, можно ли это починить где-то мимо фронт-энда. ББ эту проблему ловит, выдаёт ошибку 225 illegal sys flag.

Изображение

Автор:  adimetrius [ Пятница, 10 Июль, 2020 12:45 ]
Заголовок сообщения:  Re: Что за untagged магия?

Oleg N. Cher писал(а):
Просто для удобства и более чистого синтаксиса в КП разрешается опускать ^

Так что это операция "копирование строк по указателю".


Возражаю.
Language Report 8.1 писал(а):
If p designates a pointer, p^ denotes the variable which is referenced by p. The designators p^.f, p^[e], and p^$ may be abbreviated as p.f, p[e], and p$, i.e., record, array, and string selectors imply dereferencing. Dereferencing is also implied if a pointer is assigned to a variable of a record or array type (Ch. 9.1), if a pointer is used as actual parameter for a formal parameter of a record or array type (Ch. 10.1), or if a pointer is used as argument of the standard procedure LEN (Ch. 10.3).

Это - закрытый (исчерпывающий) список случаев, когда разыменование подразумевается и может быть опущено. Приведенный мной пример не входит в этот список. В левой части оператора присваивания указатели не разыменовываются по умолчанию.

Если строго истолковывать, то получается... ничего не получается: невозможно присвоить массив t^ указателю s. Невозможно присвоить строку "Почему это работает?!" указателю s.

Документ Platform-specific issues, который вводит понятие untagged, как я понимаю, никак не переопределяет правила совместимости по присваиванию.

Так что по-прежнему открыт вопрос: почему это работает - где это определено (кроме самого текста компилятора)?

P.S. Эта магия используется в (Lin)HostDialog.ForkOfChild, которую мы с Иван Андреичем составляли.

Автор:  Oleg N. Cher [ Пятница, 10 Июль, 2020 16:46 ]
Заголовок сообщения:  Re: Что за untagged магия?

Что же Вы возражаете на то, что я сам выше и опроверг? :-) Вы более нижние посты-то читали?

Антон, этот [untagged] не часть языка Оберон или КП. Это платформенно-специфическая особенность, отданная на откуп реализации. Возможность для низкоуровневого программирования безусловно полезная. Именно такое присвоение указателя, как Вы привели, может и недокументированное. А почему работает — вопрос философский. Ну надо так, поэтому и работает. ;-)

Автор:  adimetrius [ Пятница, 10 Июль, 2020 17:23 ]
Заголовок сообщения:  Re: Что за untagged магия?

Oleg N. Cher писал(а):
А почему работает — вопрос философский. Ну надо так, поэтому и работает. ;-)


Согласен, что польза есть. И согласен, что вопрос философский.

Но в Оберон-сообществе, кмк, несколько иная философия. Недокументированные возможности - это какая-то чуждая философия. Тем более, когда по виду - присваивание массива указателю, а по факту - а чтобы понять, что по факту, нужно либо тестик сделать, либо дизассемблировать. Это даже хуже, чем недокументированные THISARRAY и THISRECORD: они, по крайней мере, делают то, что говорят.

Автор:  Oleg N. Cher [ Пятница, 10 Июль, 2020 20:26 ]
Заголовок сообщения:  Re: Что за untagged магия?

Всё же не совсем "присваивание массива указателю". Присваивание массива системному указателю на безтеговый массив. Вернее, установка этого указателя на данные массива. Я не знал, что есть такая операция, и как-то обходился. Но всё же больше склоняюсь к тому, что это надо не выпилить, а задокументировать.

Автор:  adimetrius [ Пятница, 10 Июль, 2020 23:11 ]
Заголовок сообщения:  Re: Что за untagged магия?

Коллега, вы льете воду на мою мельницу:
Oleg N. Cher писал(а):
Присваивание массива системному указателю на безтеговый массив. Вернее, установка этого указателя на данные массива.

Это же совершенно две разные весчи. И это часть причины моего недоумения: это в буквальном смысле непонятно что (я не ругаюсь, действительно жеж непонятно!), и при этом компилятор его компилирует.

Олег, вы, как компиляторщик, глядя на текст, можете сказать, там пересылается 4 байта адреса или вся строка целиком?
А может,
s := "Почему это работает?" Пересылает строку, а
s := t^ пересылает адрес?
Или наоборот?

Надо исправить, навести порядок - и задокументировать. Потому что, безусловно, с DLL ками нужно взаимодействовать.

s := SYSTEM.VAL(PtrStr, SYSTEM.ADR("Почему это работает?"));
NEW(t, ...); t^ := "Вот это ясно, почему работает";
s := t;
(* есть ли причины это не разрешать? небезопасно, конечно, но "небезопасно" - это Untagged в переводе. и уж не опасней, чем s := t^ *)
t := s; (* запретить *)

s := SYSTEM.VAL(PtrStr, Libc.malloc(...));
s^ := "Вот это ясно, почему работает";
(* тут требуется копирование без проверки индексов; но в принципе компилятор это умеет делать *)
Libc.free(SYSTEM.VAL(Libc.PtrVoid, s));

Автор:  Oleg N. Cher [ Суббота, 11 Июль, 2020 06:24 ]
Заголовок сообщения:  Re: Что за untagged магия?

adimetrius писал(а):
там пересылается 4 байта адреса или вся строка целиком?
Только адрес. Сами массив или строка никуда не пересылаются. Прошу прощения, что выражаюсь не так ясно, как хотелось бы.

s := "Почему это работает?"; (* операция получения адреса строчного литерала, который при этом добавляется в секцию переменных и под него резервируется память в секции данных. *)
s := t^; (* операция получения адреса данных уже существующего в памяти массива (или NIL) *)

Можно считать, что s := "Почему это работает?" это то же самое, что и s := SYSTEM.VAL(PtrStr, SYSTEM.ADR("Почему это работает?"));

Изображение

Автор:  adimetrius [ Суббота, 11 Июль, 2020 11:50 ]
Заголовок сообщения:  Re: Что за untagged магия?

Oleg N. Cher писал(а):
adimetrius писал(а):
там пересылается 4 байта адреса или вся строка целиком?
Только адрес. Сами массив или строка никуда не пересылаются. Прошу прощения, что выражаюсь не так ясно, как хотелось бы.

Пачиму? похоже на пересылку всей строки ))

Oleg N. Cher писал(а):
s := "Почему это работает?"; (* операция получения адреса строчного литерала, который при этом добавляется в секцию переменных и под него резервируется память в секции данных. *)
s := t^; (* операция получения адреса данных уже существующего в памяти массива (или NIL) *)

Я вас понимаю, и это странно. Потому что понятий "адрес", "резервируется", "память", "секция данных" вообще нет в Сообщении о языке.

Предлагаю заменить такое неясное присваивание операцией ;) под названием "для своих":
s ;) "Кому надо, тот поймет";
и не документировать ее - ведь она же для своих ).

Oleg N. Cher писал(а):
Можно считать, что s := "Почему это работает?" это то же самое, что и s := SYSTEM.VAL(PtrStr, SYSTEM.ADR("Почему это работает?"));

Я, кстати, не уверен, что ADR примет константу на вход. В P-S-I сказано про адреса переменных. Но лучше переопределить ADR, чем извращать :=

Автор:  Oleg N. Cher [ Воскресенье, 12 Июль, 2020 09:15 ]
Заголовок сообщения:  Re: Что за untagged магия?

adimetrius писал(а):
Пачиму? похоже на пересылку всей строки ))
Не, ну если бы пересылалась вся строка в буфер по указателю на не выделенную память, то сразу был бы и трап, не? Кроме того, мы же видели сишный код, сгенеренный CPfront'ом. Там просто берётся указатель на строку-литерал.

adimetrius писал(а):
Я, кстати, не уверен, что ADR примет константу на вход.
В смысле, константу? Может строковый литерал? Принимает, проверил такой конструкцией:
Код:
IF SYSTEM.ADR("строка") = 0 THEN END;

adimetrius писал(а):
В P-S-I сказано про адреса переменных. Но лучше переопределить ADR, чем извращать :=
Здесь же не извращается :=
Это нормальная низкоуровневая операция присваивания указателю адреса на что-то. Кстати, даже со своеобразной проверкой типизации. Ну да, оно замаскировано под обычное несистемное присваивание, и так с первого взгляда не отделишь мух от котлет. Но присваивание есть присваивание. В Дельфи было бы:
Код:
s := @t; { Операция взятия адреса }

Страница 1 из 1 Часовой пояс: UTC + 3 часа
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/