OberonCore https://forum.oberoncore.ru/ |
|
SLICE() для передачи кусков массивов как параметров процедур https://forum.oberoncore.ru/viewtopic.php?f=29&t=6950 |
Страница 1 из 1 |
Автор: | arisu [ Пятница, 09 Июнь, 2023 13:48 ] |
Заголовок сообщения: | SLICE() для передачи кусков массивов как параметров процедур |
я тут подумал: у нас есть чудесная штука `SYSTEM.THISARRAY()`. всем хороша — кроме того, что опасная. но ведь мы можем сделать её безопасный усечённый вариант, и избавиться от постоянной передачи `arr, beg, end` и ты пы. поскольку при передаче аргументов компилятор передаёт тэг и размеры массива (иначе THISARRAY была бы невозможна), мы можем ввести безопасную функцию `SLICE(arr, beg, end)`, которая сначала проверит, правильный ли тип у `arr`, и не выходят ли `beg` и `end` за его границы, а потом просто сделает `THISARRAY()`. изменения в основном в CPP, для проверки правильного типа `arr`, и в кодогене вставление проверок `beg` и `end` (процедуры для этого уже есть). ещё я бы предложил считать `SHORTCHAR` и `BYTE` совместимыми, потому что давайте честно: знаковый байт нафиг никому не нужен, он такой потому что в жабке такой; а на деле все или сразу делают с ним `MOD 100H`, или используют напрямую `SHORTCHAR`. поэтому я вижу смысл разрешить такие слайсы. плюсы: раз и навсегда избавляемся от глупостей `arr, beg, end`, и всех связаных с ними ручных ассертов: компилятор всё сделает за нас. при декларировании совместимости шортчаров и байтов перестаём делать в апи типа Files.Reader со товарищи отдельные обёртки для обработки байтовых массивов и шортчар-массивов. (ну да, нарушение типизации в какой-то степени; ну камон, вы реально где-то использовали байты для арифметики — особенно с учётом безвариантного их расширокивания до интов при любой операции?) минусы: не вижу. если что, в компиляторе уже есть подобный чит: `arr$`. это тот же самый слайс, только менее «генерализованый». поскольку любой компилятор CP обязан такую штуку поддерживать — то можно смело предполагать, что все компиляторы будут передавать массивы как `тэг, адрес, длина`, и наличие `SLICE()` никаких дополнительных ограничений на компилятор не накладывает. изменения для mainline компилятора я сделаю, если что, вы, главное, мигните. p.s.: слайсы динамических массивов совершенно безопасны, потому что динамические массивы заякорены вызывающей процедурой. а слайс в `POINTER TO ARRAY`, натурально, не разрешается. p.p.s.: нет, библиотечно это не реализуется, в том-то и проблема. надо в язык добавлять. |
Автор: | arisu [ Пятница, 09 Июнь, 2023 14:00 ] |
Заголовок сообщения: | Re: SLICE() для передачи кусков массивов как параметров проц |
rationale: я обнаружил, что у меня куча кода или засыпана бесполезной логикой с `beg, end`, или импортирует SYSTEM только для того, чтобы сделать с массивом THISARRAY, предварительно обложив козла матами^w^w всё ассертами. в итоге, несмотря на наличие SYSTEM, на самом деле код портабельный и безопасный; и ещё каждый раз приходится boilerplate руками писать. при том, что компилятор может справиться с этим самостоятельно, и намного лучше. а. почему `beg, end`, а не `beg, len`? да фиг знает. я до сих пор не могу решить, что лучше: `beg, end` или `beg, len`, и что именно в апи использовать. собственно, сами омики тоже, поэтому в Files.Reader у них, например, `beg, len`, а в TextModel — `beg, end`. ужасно бесит, кстати, приходится помнить, где длина, а где конец. и не починишь уже, приходится с этим жить. я всё-таки склоняюсь к `beg, end`, потому что более высокоуровневая TextModel делает именно так. |
Автор: | arisu [ Пятница, 09 Июнь, 2023 20:20 ] |
Заголовок сообщения: | Re: SLICE() для передачи кусков массивов как параметров проц |
собственно, некоторое ограничение: передавать обрезки массивов можно только в процедуры, которые принимают open array. rationale: чисто техническая причина. и так пришлось в кодоген впилиться (благо, только в одно место, очень изолировано). проверка в рантайме на то, совпадает ли размер слайса с нужным, всё очень усложнит. омики для случая `a$` и параметров-массивов фиксированой длины — не поверите — делают временную переменную на стеке точно нужного размера, копируют туда строку, и потом передают временную перменную. я, конечно, тоже так могу, но вот здесь не вижу смысла. потому что один фиг копия делается — так пусть программист её явно руками делает, а не удивляется, кто стек сожрал. вся идея `SLICE()` ровно в том, чтобы избегать копирования, когда оно не нужно, а не добавлять новое. |
Автор: | arisu [ Пятница, 09 Июнь, 2023 20:23 ] |
Заголовок сообщения: | Re: SLICE() для передачи кусков массивов как параметров проц |
кстати, передача неоктрытых массивов без `IN` делает копии тоже по месту вызова, причём делается это уже силами кодогена, выделяя место на стеке через `ADD ESP, -size`. конечно, почистить это потом все забыли. ну ёлы-палы, ну… вот засунуть такое в длиииинный цикл — и офигеть от того, что внезапно, на пустом месте, закончится стек. какого чёрта это не делается в вызываемой процедуре? отсюда запомните правило хорошего тона: никогда не вызывайте в цикле процедуру, которая принимает неоткрытый массив без `IN`. короче, иллюстрация: Код: TYPE S10 = ARRAY 10 OF CHAR; делается две копии `b`. будет цикл — будет овердофига копий, место на стеке выделяется каждый раз. по-моему, это тупо баг, ребята забыли подкорректировать ESP в финале.PROCEDURE Str2Proc (a: S10); PROCEDURE TestStr12; VAR b: S10; BEGIN Str2Proc(b); (* тут мы делаем копию b на стеке через ADD ESP *) Str2Proc(b); (* а тут ещё раз, забыв убрать старую копию, снова через ADD ESP *) END TestStr12; но. Код: PROCEDURE Str0Proc (a: ARRAY OF CHAR); копии `b` делаются внутри `Str0Proc`, так что такой вызов из цикла безопасен.PROCEDURE TestStr13; VAR b: S10; BEGIN Str0Proc(b); Str0Proc(b); END TestStr13; Код: PROCEDURE Str1Proc (IN a: S10); никаких копий.PROCEDURE TestStr13; VAR b: S10; BEGIN Str1Proc(b); Str1Proc(b); END TestStr13; Код: PROCEDURE Str1Proc (IN a: S10); а вот тут всё происходит уровнем выше: заводятся две скрытые локальные перменные (по количеству вызовов). такая ерунда в цикле безопасна. то есть, место на стеке выделяется один раз, по визуальному счёту вызовов. собственно, реальный AST:PROCEDURE TestStr14; VAR b: S10; BEGIN Str1Proc(b$); Str1Proc(b$); END TestStr14; Код: PROCEDURE TestStr14
VAR @str0: ARRAY 10 OF CHAR VAR @str1: ARRAY 10 OF CHAR VAR b: S10 BEGIN COMPOUND @str0 := b$; CALL Str1Proc(@str0$); END COMPOUND; COMPOUND @str1 := b$; CALL Str1Proc(@str1$); END COMPOUND; END TestStr14 |
Автор: | arisu [ Суббота, 10 Июнь, 2023 08:58 ] |
Заголовок сообщения: | Re: SLICE() для передачи кусков массивов как параметров проц |
реализовал PoC. как и сказано — передавать слайсы можно только в процедуры, которые принимают open array. сделано не очень красиво, но я хотел по минимуму врезаться в кодоген. поэтому в кодогене добавлена отдельная процедурка в `DevCPV.ActualPar()`, а в DevCPB делается акробатика по переписыванию `SLICE(arr, beg, end)` в нечто типа: `SLICE(arr[beg], COMP(ASSERT((end >= beg) & (end <= LEN(arr)), inxTrap), end - beg))`. отдельная процедурка понадобилась затем, что кодоген такие компаунды не понимает, так что я использую компаунд чисто как контейнер для нод (анализаторы AST такие контейнеры понимают правильно). как и полагается, если индексы — константы, и размер массива известен на стадии компиляции, то проверки будут сделаны на стадии компиляции, и в финальный код не попадут. это само собой получается за счёт constant folding. присваивание слайсов не поддерживается. в смысле: `arr1 := SLICE(arr2, b, e)` распарзится, но потом компилятор обидится, потому что фича исключительно для параметров. опять же: сделать можно, но я не хочу. в принципе, генерируемый код можно сделать получше, если более глубоко влезть в низкоуровневый кодоген, но я пока стараюсь его не трогать. тащемта, просто потому, что ещё не разбирался толком, как он работает в плане выделения регистров и прочего (общую картину я понимаю, но в нюансы не лазил). |
Автор: | arisu [ Суббота, 10 Июнь, 2023 11:51 ] |
Заголовок сообщения: | Re: SLICE() для передачи кусков массивов как параметров проц |
ох, блин… омики меня в очередной раз обманули: нет у них ошибки с балансировкой стека. эти хитрые жуки чистят стек в вызываемом коде, через `RET оченьмного`. простите за дезу, вчера с устатку недосмотрел. вот поэтому я пока и не хочу лазить в низкоуровневый кодоген, например. |
Автор: | arisu [ Суббота, 10 Июнь, 2023 11:59 ] |
Заголовок сообщения: | Re: SLICE() для передачи кусков массивов как параметров проц |
вообще, интересно, кто у них кодоген для X86 делал. чувак с… неортодоксальным мышлением. это не в смысле завуалированого оскорбления, совсем наоборот: я восхищаюсь. потому что кодоген в CP2 не очень похож на OP2. то есть, совсем не похож, хотя основная идея сохранена. |
Автор: | SovietPony [ Среда, 14 Июнь, 2023 12:30 ] |
Заголовок сообщения: | Re: SLICE() для передачи кусков массивов как параметров проц |
arisu писал(а): вообще, интересно, кто у них кодоген для X86 делал Судя по заголовку в CPV486 - Beat Heeb. Кроме того, по комментам очевидно, что любые значитльные кромсания компилятора за его же авторством (DTC, CP, кодоген 486).
|
Страница 1 из 1 | Часовой пояс: UTC + 3 часа |
Powered by phpBB® Forum Software © phpBB Group https://www.phpbb.com/ |