![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
SOL (Соль) = Simple Objects Language
Vladimir Kladov © (2007-12-15 22:08:00)http://kolmck.net/sf/SOL=IdealSpade4Programmer.rar
Ну хорошо, пусть будет отдельная ветка.
Сразу ответ D[u]fa на
зачем каждый раз писать do, почему б нельзя объявить массив как arr[... , ..., ...]
Мы же пишем begin, и нормально. Анализ текста значительно упрощается. Дело даже не в компиляторе. Человеку тоже проще, если есть открывающая скобка блока. Есть ведь и эквиваленты, кому само слово DO не нравится (и END).
Массив не надо так объявлять. Я долго думал, почему. Например, во избежание непонимания того, что если есть объявление [3,3,3], то можно обратиться как [i,j] и получить элемент-масив из 3 элементов. Если можно объявлять только [3][3][3], согласитесь, такой проблемы вообще нет. В конце концов, ][ ничем не хуже , ,но видно этот "символ" лучше.
Спрашивайте ещё. Я пока пытаюсь "победить" многозадачность (точнее многонитевость). Изучил адовские рандеву, мониторы модулы-2, активные объекты эктив-оберона - ничего мне не нравится пока. И вообще. Механизм защиты CATCH, который я предложил как черновой, мне самому трашно не нравится. В общем, голову ещё есть над чем поломать.
Vladimir Kladov (2007-12-23 17:27:00) [81]vpbar> При этом все "слабые" указатели, указывающие на этот объект,
> автоматически получают значение NIL.
А вот это мне нравится. Хотя тут было подобное обсуждение, и со мной стали спорить, что такое нельзя сделать.
Где было обсуждение?
Сделать можно, 2мя способами. 1) "умные указатели". Каждый блок в памяти (который в SOL всегда является динамическим объектом с VMT, будь он структура, или динамический массив) обратно ссылается на smart-pointer (это термин С++, как они там с этим борются), по памяти никак не перемещаемый, а все указатели на объект указывают не на объект, а не смарт-поинтер. Надо присвоить NIL - это значение записывается в smart-указатель, и вуаля.
Мне это решение не очень нравится, т.к. требуется двойная косвенность.
2) Теперь простой вариант, хотя и кажетсяна первый взгляд неэффективным. Каждый указатель - это 2 адреса: один на сам объект второй - на следующий в циклической цепочку указателей на тот же самый объект. И опять, динамический объект обратой ссылкой смотрит на один из указателей, которые смотрят на него. А т.к. все такие указатели образуют кольцо, то они все перечислимы, сколько бы их ни было. И всегда можно пройтись по кольцу, и присвоить всем указателям NIL (причём, обоим адресам в этих указателях, разорвав кольцо).
Этот вариант кажетсянеэффективным. На самом деле, он эффективнее вдвое, чем первый. Ведь не часто бывает так, что на одно и то же указывает сразу слишком много указателей. Ну, указатели стали вдвое больше, нужно два адреса хранить. Не думаю, что из-за этого возникнут проблемы с нехваткой памяти. Зато косвенность остаётся одноуровневая.
Впрочем, можно и оба варианта реализовать, и просто переключаться в опциях.
Обратная ссылка из динамического объекта на "свои" указатели позволяет сделать ещё одну важную и полезную вещь: автоматическую дефрагментацию кучи(в обоих приведённых вариантах). Если программа должна работать долго, памяти требует прилично, память постоянно выделяет и освобождает, кусками весьма разного размера, и куча не дефрагментируется, то рано или поздно придёт капец, и нельзя будет выделить блок сколько-нибудь приличного размера хотя бы и в несколько сот килобайт. Потребуется перезагрузка. Но для алгоритмов с непрерывным циклом это может быть недопустимое решение проблемы. Разумеется, дефрагментация должна быть опциональна.
(Чего я это пишу по новой? Это уже всё написано в большом тексте).
vpbar (2007-12-23 17:05:00) [82]
> Так, я кажется забыл написать
Кажеться, хотя я почти догадался что это так. Про указатели есть то что они инициализируются нилом, а про остальное нет.
> При этих условиях const, in, var и out - совершенно ненужный
> семантический мусор для параметров.
Может быть, может быть. Просто мне больше нравится сказать компилятору что данный out парамеот должен обязятельно быть изменен в функции.
> Функциональными языками попахивает
Еще как :).
> никто даже не трогает проблему сборщика мусора
Вы выложите тему в прочее, там Зотов (если не ошибаюсь может и Шевченко, давно было это) с вами поспорит. По-поводу неопределенности вызова деструктора, финализаторов и прочего. По мне у вас интересное решение. Но пока я не представляю как будут организованы сложные структуры данных с вашими разношерстными указателями. У сборщик мусора есть - и хорошо. Нет - и тоже не проблема, имхо.
Ну нету в Delphi шаблонов, и не надо
Vladimir Kladov (2007-12-23 16:44:00) [83]Не совсем трассировкой, но суть в том, что на каждой вложенной процедуре в стек подаётся ещё один скрытый парамтр - вектор из базовых адресов локалов каждой из процедур верхнего уровне, к переменным которой ей может понадобиться обратиться. К тому же обращения получаются всегда косвенные через базы, которая лежит на стеке, что весьма накладно по сравнению с прямым доступом к локальным переменным.
function name(s:string; in x:Type; inout io:Type ;out e:TError):Type;
Тут штука в том, что по неизвестной мне причине разработчики компиляторов избегают анализа между процедурами, т.е. стараются сделать так, чтобы компилятор рассматривал каждую процедуру/функцию как "чёрный" ящик. Это наверняка упрощает дело, но я собираюсь выполнять такой анализ. Т.е. когда компилируется A, вызывающая B, то даже если ещё не готов результат компиляции B полностью, для неё уже точно будет известно о каждом параметре, есть ли (возможны ли) попытки изменить параметр внутри функции B, или если не в ней самой, то в тех функциях, которые она вызывает, передавая адрес своего параметра вместо самого параметра в качестве параметра тех функций.
Соответственно, компилятору это и так известно. Человеку это и не интересно, для него известно точно, что если передаётся адрес явно, то параметр может измениться (он хочет чтобы он изменился), а если передана просто переменная, то измениться она не может. Это упрощает, хотя может быть и не очень (и совсем не) эффективно, если передаётся большая структура или массив по значению, и модифицируется внутри (но я думаю и с этим случаем маленько побороться - техникой copy-on-write, например).
Так, я кажется забыл написать, что я собираюсь инициализировать все переменные значением по умолчанию. В голове-то оно у меня есть, потому что уже отвечал в письме товарищу одному, да. Но, видимо, я забыл подыскать место в текстах, куда это впихнуть. В общем, это обязательный момент, и касается всех переменных, локальных и глобальных, и не только указателей. Оставался ещё открытым вопрос насчёт динамических массивов, будут ли они неявно инициализироваться по Allocate (наверное, всё-таки нет, кроме случая массива указателей, указатели всегда должны быть равны NIL изначально). Если инициализатора у переменной нет, то нулями (но тогда 0 должен быть в диапазоне, а если нет нуля в диапазоне, и нет инициализатора, то ругаться будет и откажется дальше компилить).
Идея не в том, чтобы проинициализировать всё, даже то, что инициализацировать не требуется, а в том, чтобы задать формально некоторые начальные условия, от которых пляшет комилятор. Т. е. если он видит что переменная передана из A в B неинициализированной, а она в B требуется уже в нормальном состоянии, то он её проинициализирует до передачи значением по умолчанию. Само собой, нет смысла инициализировать переменную, начальное значение которой не нужно, и ей будет присвоено значение (в B).
При этих условиях const, in, var и out - совершенно ненужный семантический мусор для параметров. Немножко междупроцедурного анализа, и всё само собой устаканивается (с одним различием - указатель или значение). Разумеется, надо контролировать весь граф вычислений, что кому и когда присваивается, но на это компилятор и нужен, по-моему.
Вариант с полным разделением входов-параметров от выходов-структуры мне приходил в голову. Но я отказался сразу же. Неудобно это. Функциональными языками попахивает. Как бы идея и неплохая, но лишней мороки может быть много с переходом мышления на такую линию. (У меня и так несколько революций в языке).
Вот интересно: никто даже не трогает проблему сборщика мусора. Наверное, программеры Delphi просто мало знают, о чём идёт речь, и почему моё решение проблемы GC - это кровавая революция с отрубанием голов всех ныне сущих языков с GC, включая Java, Oberon и всего .NET.
Так же мне очень хорошо понятно, что проблема надёжной многопоточности если и осознаётся в принципе, то всё равно не слишком много народу готовы обсуждать моё решение и степень его идеальности. Нужно на своей шкуре испытать, что это такое, отладка многопоточной проги с тесным взаимодействием между потоками по данным, чтобы проникнуться.
Я даже понимаю, что проблема шаблонного программирования не понятна программерам на Delphi. Ну нету в Delphi шаблонов, и не надо: обходимся же динамическим полиморфизмом (указатель функции как параметр алгоритма).
Но вот что хотелось бы услышать: отношение к проблемам повышения локальной читабельности (без скачков по тексту, в задействованные модули и функции, в описания переменных, типов и т.п.), максимального переноса проверок на время компиляции (в том числе SQL), отделения ассемблера от языка с сохранением ассемблирования на этапе компиляции, ...
В общем, пойду-ка я и правда попробую составить что-то типа сравнительных таблиц. Я не уверен, что хорошо знаю некоторые малораспространённые языки, вроде Ады или Оберона, но если что, меня поправят.
vpbar (2007-12-23 16:14:00) [84]
> Как только последняя такая ссылка исчезает...., объект разрушается.
> При этом все "слабые" указатели, указывающие на этот объект,
> автоматически получают значение NIL.
А вот это мне нравится. Хотя тут было подобное обсуждение, и со мной стали спорить, что такое нельзя сделать.
homm (2007-12-23 16:13:00) [85]> [68] vpbar © (23.12.07 16:08)
> И без всякой трасировки.
Ну а как, тогда? Может указатель на начало стека родительской процедуры всегда сохраняется?
vpbar (2007-12-23 16:08:00) [86]>>homm © (23.12.07 15:46) [67]
Ээ. Дык в делфи например это работает. И без всякой трасировки.
homm (2007-12-23 15:46:00) [87]> [66] vpbar © (23.12.07 15:33)
> К томуже вложеность тут не играет роли.
А теперь представь, что вложенная функия орбащается к переменным (стеку) родительской функции. Притом сама выделяет некое количество переменных на стеке. Вопрос: как еще, кроме как трассировкой стека функция может получить доступ переменным родительской, если она вызывается рекурсивно? (может я ошибась? что-то правда все грустно получается…
vpbar (2007-12-23 15:33:00) [88]Стеб только тут "Сильный аргумент :)." В остальном просто попытка понять идею путем уточнения непонятных моментов.
> Кроме того, я советую задуматься, как (насколько эффективно)
> вложенные функции реализуются в машинном коде.
Насколько я понял главной целью языка не является упрощение и оптимизация копмилятора. К томуже вложеность тут не играет роли. Разве в Соль нельзя вызвать функции рекурсивно? При том что "Область определения функции - весь модуль" они могут тоже довольно запутано вызываться. Так что, имхо, это не агрумент.
> Читайте внимательно. Надо, чтобы изменялось внутри функции
> - передаём указатель.
Читаю. Не все еще прочитал, но вряд ли дальше это описывается.
Допустим есть такое определение на неком гипотетическом языке. Но суть думаю понятна будет.
function name(s:string; in x:Type; inout io:Type ;out e:TError):Type;
Параметр x должен быть инициализирован до вызова, не может менятся внутри функции. e - должен быть инициализирован внутри функции. io - передается по ссылке. Т.е. это дает определенный контроль за вызовом функции.
Как это описать в Соль? Я пока не нашел. В принципе в некоторых случаях можно все "выходы" функции возвращать в результате-кортеже. А то, что какойто входной параметр может менятся у вас указывается ссылкой на него. Но вообщем я не пришел к заключению как лучше (У меня тоже возникла похожая идея. Обобщить функцию до отношения между кортежами).
Vladimir Kladov (2007-12-23 10:21:00) [89]English verion of short (but not very short) specification is ready:
http://kolmck.net/sf/SOL%20-%20short%20description.English.htm
Sorry for my English but you know that it is not my native language.
Заодно русский вариант поправил. Кстати, если кто-то (вдруг) осилил полное описание и обнаружил, что в коротком чего-то важное забыто или не совпадает, пожалуйста, подскажите на недостатки.
Vladimir Kladov (2007-12-23 02:10:00) [90]
Вложеные функции иногда удобны хотя бы для ограничения видимости.
Когда их мало, может быть и неплохо. Когда их много... Начинаются ошибки. Компилятор уже не сообщает о неинициализированных переменных, становится возможным использование имени переменной с большей областью видимости как локальной по ошибке, отсюда непредсказуемые побочные эффекты. Кроме того, я советую задуматься, как (насколько эффективно) вложенные функции реализуются в машинном коде. Особенно в случае, если допускается рекурсивный вызов вложенных функций, и в особенности, если вложений несколько, и на нескольких уровнях, и рекурсивные цепочки вызовов могут быть неоднозначны. Кроме того, лазить по такому исходному коду - проще застрелиться.
(В
данном случае это не стеб). Идею дарюА в остальных случаях - стёб? Спасибо но мне не надо такой идеи. Дочитаете до моих методов, поймёте что в этом смысле они у меня как в Обероне - просто функции.
А параметры константы, in out ref и все прочие декларации как?Не неужны. Читайте внимательно. Надо, чтобы изменялось внутри функции - передаём указатель. Если передаём массив по значению, и внутри он изменяется (а раз по значению, то не изменяется снаружи), компилятор ругается, но делает как приказано. Передаётся по значению, но не изменяется, компилятор передаёт указатель неявно. Хотим, чтобы массив изменился на самом деле - передаём указатель на весь массив. В 2х последних случаях компилятор молчит, и передаётся указатель.
Или функция возвращает тоже
структуру?Не вижу никаких проблем с возвращением структуры или массива.
vpbar (2007-12-23 00:31:00) [91]Приветствую, тезка.
Эээ.
Как я понял от GOODWELL почти ничего не осталось. Жаль . Он мне больше нравился. Я даже некоторые идеи подогнал для своего мега языка :)
Теперь по теме
> В языке Паскаль существует правило, запрещающее изменять
> значение счётчика цикла в теле цикла. Возможно, это сделано
> для того, чтобы не мешать компилятору оптимизировать выполнение
> цикла. В Си такого ограничения не существует. Думается,
> что в простом языке такого ограничения так же не должно
> быть. Не изменяется - хорошо, изменилось - в чём проблема?
> Ведь всё равно данное ограничение обходится в том же Паскале
> переписыванием цикла типа for на цикл типа while.
А возможно это сделано для для того чтобы выделить цикл со счетчиков в отдельную конструкцию. Поскольку семантически они немного разные. И эмулировать цикл с постусловием циклом с предусловием тоже, имхо, не совсем хорого.
> В отличие от Паскаль-подобных языков, мы не будем разрешать
> размещать функции вложенными друг в друга. Это, по крайней
> мере, упростит разработку компилятора.
Сильный аргумент :). Но непоследовательно в одном случае усложнять компилятор (определение типов) а в другом упрощать. Вложеные функции иногда удобны хотя бы для ограничения видимости.
> Посмотрите, что произойдёт в случае, если мы так же введём
> в язык ограничение на число передаваемых функции параметров.
> Например, одним-единственным возможным параметром (упрощать,
> так упрощать!).
Я предлагаю еще упростить. Сделать функцию объектом с методом напимер execute и полями, которые по сути параметрами будут. (В данном случае это не стеб). Идею дарю. Конечно компилятор немного усложнится (ничего в другом можно упростить :) ) - ему придется проверять инициализированы ли все поля до вызова (хотя тут и значения по умолчанию могут быть). Зато есть плюсы. Например повторный вызов если изменен только один параметр короче будет.
А параметры константы, in out ref и все прочие декларации как? Как описание полей структуры? Или функция возвращает тоже структуру?
Все. жена пришла из душа :)
Удачи в новом начинании.
Vladimir Kladov (2007-12-22 19:06:00) [92]Сегодня я выложил версию 14. Добавил про сравнение типов и чуть более подобно описал, что такое шаблоны (абстрактная запись алгоритмов без привязки к конкретным типам данных) и как с ними бороться. Английский уже 2/3 готовы. Надеюсь успеть за выходной.
Vladimir Kladov (2007-12-22 19:03:00) [93]Я бы рад принять предложение, но там это уже как бы есть. Я все-таки предлагаю ознакомиться. Хотя для начала в том варианте который краткий, но не самый краткий.
misha_shar (2007-12-22 14:14:00) [94]Хорошо я так понял идет обсуждение спецификаций языка.
Предлагаю сделать набор операций расширяемым. Где нибудь в
начале программы дополнительным операциям сопоставить программы
выполнения этих операций определенного типа. А затем компилятор
заменяет операцию на обращение к функции.
Vladimir Kladov (2007-12-22 10:16:00) [95]Я документацию выложил, см. первый пост. Самого языка ещё нет, а вам уже компилятор подавай. Компилятор я думаю начать делать в ближайшее время. Только сначала переведу на английский хотя бы сжатое описание. Длинное описание - это последовательность непоследовательных мыслей, скорее. В кратком описании есть практически всё, и синтаксис, и семантика, и даже кратенькие примерчики. Длинное описание имеет смысл читать, если заинтересовало сжатое. Совсем краткое (справочник) я думаю вообще убрать. Кстати, если кому интересно попробовать составить БНФ или ЕБНФ схему синтаксиса, я был бы не против. К моему сожалению, я не считаю, что БНФ даёт хоть какую-то пользу, я её даже читать не могу, не приемлет мой мозг, для меня это что-то write-only текста. Но интересно было бы всё-таки иметь формальное описание синтаксиса, чтобы просто численно сравнить сложность (есть такое сравнение, проделанное для порядка дюжины языков. Кажется мне, оно несколько субъективно и Оберон получается самым простым ЯВУ. К сожалению, стандарт Оберона-2 мало что может, а расширения - это уже не он сам).
misha_shar (2007-12-22 07:56:00) [96]А посмотреть и попробовать сам язык можно? Хоть какой то транслятор
есть? Вообще кроме документации еще что нибудь есть?
Vladimir Kladov (2007-12-22 07:41:00) [97]Нет про RAD речь действительно не идёт. Сначала делается компилятор и редактор, потом библиотек, а уже потом RAD. По-моему, RAD возникает как расширенное средство редактирования исходного кода, в виде связи между визуальными компонентами и исходным текстом, или иначе - в виде ещё одного внешнего представления исходного кода.
Бельчонок (2007-12-21 21:12:00) [98]Я конечно всю документацию не читал, то ли терпения не хватило, то ли времени... но на сколько я понял, пока получается только компилятор, как в FPC, т.е. о RAD даже речи не идёт, всё ограничивается простым (ну или навороченым) текстовым редактором? Если нет, то придётся с нуля писать кучу библиотек, так когда же ждать бету (хотя бы под виндоус)?
Vladimir Kladov (2007-12-21 18:48:00) [99]под какую ось все планируется
Под все оси, под всё железо, под FPGA, под всё, что угодно. Это универсальный язык, и ему начхать даже на то, какая система счисления в этой машине.
Это язык не ради языка, а ради больших задач. Что такое многопоточность в макроассемблере под названием Delphi, я уже прочувствовал.
D[u]fa (2007-12-21 17:24:00) [100]>Язык ради языка - мертворожденный!
это про что?
Vladimir Kladov, я как то пропустил.. а под какую ось все планируется?