Оберон-клуб «ВЄДАsoft» https://zx.oberon.org/forum/ |
|
Константные массивы https://zx.oberon.org/forum/viewtopic.php?f=8&t=213 |
Страница 1 из 7 |
Автор: | Zorko [ 27 июн 2014, 23:35 ] |
Заголовок сообщения: | Константные массивы |
Ещё наверное будет нелишним ответить на вопрос: зачем вообще приходится городить что-то подобное вышенаписанному? Да дело в том, что в Обероне (1, 2, 07 и КП) нет константных массивов. Ресурсы там предлагается подгружать из файлов или присваивать поэлементно. Считаю этот недостаток Оберона, пожалуй, самым досадным. Я очень хочу его исправить хотя бы в XDev, тем более, подобные попытки уже делались в Active Oberon, Extacy Oberon-2, Amiga-Oberon v3.11, F. Siebert / A+L AG. И синтаксис предложен: Код: "OBERON"
|
Автор: | Saferoll [ 29 июн 2014, 14:39 ] |
Заголовок сообщения: | Re: Константные массивы |
Код: "OBERON"
Код: "OBERON"
или что-то иное? |
Автор: | Zorko [ 29 июн 2014, 20:19 ] |
Заголовок сообщения: | Re: Константные массивы |
Так точно. А для компиляторов чистого Си, в которых не предусмотрено слово const (а такие компиляторы есть, ибо const появилось в C++) можно вынести определение в SYSTEM.h: Код: "C" #ifdef __cplusplus Меня в реализации этой фичи смущает то, что мы этим подошли к заданию явно типизированных констант, а значит логично будет поддержать не только массивы, а и что-то такое: Код: "OBERON"
|
Автор: | Saferoll [ 30 июн 2014, 21:00 ] |
Заголовок сообщения: | Re: Константные массивы |
Zorko писал(а): Меня в реализации этой фичи смущает то, что мы этим подошли к заданию явно типизированных констант, а значит логично будет поддержать не только массивы, а и что-то такое: А типизированные константы будут чем-то отличаться от обычных? Код: "OBERON"
0 - это константа типа SHORTINT, т.к. это наменьший диапазон, ее содержащий. Код: "OBERON"
|
Автор: | Zorko [ 02 июл 2014, 00:30 ] |
Заголовок сообщения: | Re: Константные массивы |
В языке Оберон (1, 2, 07 и КП) тип константы берётся из контекста описания, и вобщем-то это достаточно удовлетворительно. Не знаю как компилятор хранит константы внутренне, но совместимость SHORTINT => INTEGER => LONGINT => REAL позволяет указать внутренний тип константы в минимальный, а потом при подстановке значения приводить по мере необходимости к большему типу если это потребуется. Но можно назвать пару случаев (их наверное может быть больше) когда имеет место неоднозначность:
Так что не знаю насколько большой будет доработка Ofront'а. Но, в принципе, если уж разрешать такое прямое уточнения типа константы: Код: "OBERON"
Ещё, кстати, как быть, разрешать ли такое? Код: "OBERON"
|
Автор: | Zorko [ 02 июл 2014, 00:46 ] |
Заголовок сообщения: | Re: Константные массивы |
Проверил. TurboPascal 7.1 такое компилирует: Код: "OBERON"
Код: "OBERON"
|
Автор: | Saferoll [ 02 июл 2014, 20:32 ] |
Заголовок сообщения: | Re: Константные массивы |
Zorko писал(а): И я уверен, что CONST a = LONG(LONG(0)) здесь не поможет. Действительно, тип константы определяется ее значением. Так числовая константа в какой наименьший тип влезла, такого типа она и есть. Вместо константы-литерала везде можно использовать константное выражение, но после вычисления такого выражения получается число. И тип выражения определяется этим числом, как если бы оно было изначально задано. Так что, LONG(0) и 0+0 и 0-0*0 дают в результате "0", а значит представляют собой просто другой способ записи "константы ноль".Вот переменные - другое дело, тут тип определяется не текущим значением, а потенциальными возможностями хранилища. Пусть сейчас там ноль, но ведь может быть и другое значение. Если VAR x:INTEGER, то выражение LONG(x) имеет тип LONGINT (даже если х=0 в данный момент). В ТурбоПаскале были так называемые "типизированные константы", которые по сути были не константами, а переменными. Их можно бы назвать "преинициализированными переменными с глобальным временем жизни". А вот константа CONST a = LONGINT(0); больше заслуживает название "типизированная" - это константа у которой есть не только значение, но и особый тип (к значению дополнительно приклеен "ярлык", "тэг" с названием типа). Переменная обязана уметь хранить любое значение своего типа, для чего ей выделена память соответствующего размера. У типизированной константы значение уже задано и не изменится, так что память для всего диапазона значений можно не выделять, но компилятор где-то должен хранить ее тип. Типизированная константа (настоящая, а не турбопаскалевская) - это некий гибрид между переменной и константой, в большей степени это константа, но на переменную она похожа наличием типа. Введение таких констант в компилятор усложнит вычисление константных выражений. Сейчас выражение из констант сначала вычисляется, а потом по результату определяется его тип. При наличии типизированных констант тип придется вычислять непрерывно, одновременно со значением. Но это и правда снимет неоднозначности в некоторых случаях, например таким образом можно будет задавать знаковые и беззнаковые константы (когда таковые появятся). Цитата: Так что не знаю насколько большой будет доработка Ofront'а. Но, в принципе, если уж разрешать такое прямое уточнения типа константы: А вот константные массивы - это уже нечто другое, чем LONGINT(0). Потому что, числовые константы были изначально, пусть даже их тип задавался значением, а не явным указанием. А вот массивов-констант какого либо типа не было (за исключением, разве что, цепочек символов). Как они должны толковаться семантически? Как IN-параметры, полученные откуда-то извне? AnimClockData[0] - это константное выражение? Можем ли мы передать такой массив в процедуру фактическим параметром, только ли по значению или как IN тоже можно?Код: "OBERON"
Обычная константа задается только своим значением и это значение собственно сама константа и есть. Типизированная константа кроме значения имеет тип, поэтому INTEGER(0) и LONGINT(0) имеют одинаковое значение и разный тип. Константный массив видимо имеет еще и адрес, который и передается в процедуры. Цитата: Ещё, кстати, как быть, разрешать ли такое? Код: "OBERON"
А это уже константный массив анонимного типа. Навроде, Код: "OBERON"
Лучше бы вводить новые фичи постепенно, исходя из практической потребности. Скажем, для начала можно ввести константные массивы неанонимного типа, семантически толкуя их как полученные извне IN-параметры. Это, думаю, будет проще реализовать и пока для практики достаточно. |
Автор: | Zorko [ 02 июл 2014, 21:36 ] |
Заголовок сообщения: | Re: Константные массивы |
Да, наверное ты прав, Олег. Так и нужно сделать. |
Автор: | Saferoll [ 03 июл 2014, 17:29 ] |
Заголовок сообщения: | Re: Константные массивы |
Ну и пока, я думаю, следует ограничиться одномерными массивами (константные выражения в скобках через запятую). Тогда план реализации такой: 1) Находим в парсере (модуль ОРР) то место, что генерирует ошибку на TheClocks в строчке CONST AnimClockData = TheClocks (...) 2)Ставим там условие, что прочитанный идентификатор является одномерным массивом из ... ну на первых порах можно числовыми типами ограничиться. 3)Если это действительно так, то создаем в памяти кусок для хранения этого массива (тип элементов и их количество ведь известны) 4)Дальше берем кусок кода из ActualParameters, потому что элементы в скобках синтаксически похожи на список фактических параметров. И если ActualParameters строит список параметров fpar, то здесь нужно помещать считанные константные выражения в наш выделенный кусок. Конечно, нужно по пути контролировать тип и константность. И количество тоже проконтролировать. 5) Получили новый узел в дереве со ссылкой на эти элементы. Этот узел нового типа, поэтому как-то нужно это пометить. 6) В модуле OPV в том месте, который обрабатывает узлы такого типа, пишем генерацию текста на Си: выводим элементы через запятую по столько-то в строке (по 10 или 16, например). Это то, что касается описания константного массива. Кроме этого, нужно запрограммировать использование. При использовании можно обращаться с таким массивом, как будто он массив, поступивший откуда-то извне как IN-параметр. В том числе и в секции инициализации модуля, хотя у модулей нет входных параметров (и вообще никаких). Вот тут уже так подробно наметить реализацию я затрудняюсь. |
Автор: | Saferoll [ 13 июл 2014, 19:58 ] |
Заголовок сообщения: | Re: Константные массивы |
Приступил к реализации этого плана: Saferoll писал(а): 1) Находим в парсере (модуль ОРР) то место, что генерирует ошибку на TheClocks в строчке CONST AnimClockData = TheClocks (...) 1,2) место в модуле ОРР нашел -это PROCEDURE Block, самое ее начало:2)Ставим там условие, что прочитанный идентификатор является одномерным массивом из ... ну на первых порах можно числовыми типами ограничиться. Код: "OBERON"
Цитата: 3)Если это действительно так, то создаем в памяти кусок для хранения этого массива (тип элементов и их количество ведь известны) 3,4) Пишем новую процедуру ConstArray(x) на основе ActualParameters. Можно поместить ее внутри процедуры Block, но я вынес наружу перед Block (возможно константные массивы понадобятся в дальнейшем где-то еще):4)Дальше берем кусок кода из ActualParameters, потому что элементы в скобках синтаксически похожи на список фактических параметров. И если ActualParameters строит список параметров fpar, то здесь нужно помещать считанные константные выражения в наш выделенный кусок. Конечно, нужно по пути контролировать тип и константность. И количество тоже проконтролировать. Код: "OBERON"
Но вот где в дереве хранить сам этот массив? В узлах не предусмотрены ссылки на произвольные двоичные данные (BLOB). Можно ввести тип POINTER TO ARRAY OF LONGINT (например), выделить при помощи NEW память нужного размера и разместить там массив. Но потом указатель на этот массив нечему присвоить, узел не содержит поле необходимого типа. Один из путей - не переделывать узлы, и не выделять сплошной кусок памяти, а распихать байты в имеющиеся поля узла (поля BYTE,INTEGER,LONGINT, OPS.String и т.д.). Но придется писать процедуры "распихивания" и "извлечения" обратно, да и заняты в узле будут только некоторые поля, а остальные болтаться попусту. И к тому же много так не распихаешь-ну около 50 байтов на узел. Лучше изменить тип ObjDesc или ConstDesc, добавив туда указатель на открытый массив байтов. Единственный недостаток - это поле будет болтаться попусту, если двоичных данных у узла нет. Но один лишний указатель на узел -расход невеликий. К тому же это поле пригодится и в дальнейшем, например для двоичных процедур или чего-то подобного. Кстати, в ConstDesc уже есть нечто подобное - поле ext типа OPS.String для хранения строчки inline-процедуры (PROCEDURE-). Новое поле позволит увеличить длину такой процедуры до нескольких строчек. Так что, думаю, нужно дополнительное поле (назовем, скажем blob, кто-то предложит более удачное?). Вот только куда его лучше вставить? Логичнее в ConstDesc, потому что этот набор данных действительно константы. Код: "OBERON"
Тогда в ConstArray можно будет выделить память NEW(x^.conval^.blob,size);, где size расчитывается из n и размера данных (OPM.IntSize и пр). Хотя лучше создать спецпроцедуру OPB.NewBlob. Но это будет массив байтов, типы LONGINT и другие надо будет разбить на байты и туда записать, а в OPV при генерации С-программы наоборот из байтов собрать значение. Как наиболее эффективно это сделать, есть ли что-то специально для этого в SYSTEM, кроме DIV, MOD и сдвигов? |
Страница 1 из 7 | Часовой пояс: UTC + 2 часа |
Powered by phpBB® Forum Software © phpBB Group https://www.phpbb.com/ |