Здравствуйте, Sm0ke, Вы писали:
N>>1. Общая направленность — системный, прикладной на какой-то класс задач.
S>Назначение языка — для любых задач.
Уже не бывает. Надо определиться.
S>И для gui, и для научных расчётов, и как встроенный скриптовый движок приложений/игр.
N>>2. Процедурный, функциональный, что-то посредине.
S>Наверно это микс.
S>Структура файла:
S>* Имя модуля
S>* Декларативная часть (определение ячеек модуля, то есть свойств модуля)
S>Элемент декларативной части начинается с имени ячейки, или с разрешённой для декларативной части команды.
S>Ячейка может содержать что угодно. И тип, и функцию, и последовательность выражений (sequence), и просто значение
S>Таким образом не нужно писать как в си++ using type_alias = int;
S>А просто type_alias = $int
S>Аналогично для функций:
S>S>fn_alias = other_fn
S>
Ничего из этого пока что не даёт функциональный язык. Вижу процедурщину в чистом виде. Это не плохо, но это характерно.
S>>>*- Императивный кусок кода помещается в фигурные скобки и имеет тип $seq (sequence).
N>>Тогда надо сразу сказать, что будет в неимперативных кусках.
S>В декларативной части можно:
S>S>имя_ячейки = ( /* expression */ )
S>имя_ячейки = /* команда опеделения */
S>имя_ячейки = { /* последовательность выражений, тут императивная часть */ }
S>имя_ячейки /* команда-модификатор */
S>
Это просто вынесенная вперёд часть инициализаций, ничего пока особенного.
N>>3. Управление памятью: ручное (как в C, C++), автоматическое полностью (как в Java, C#), на владении ссылками (Rust), смешанное.
S>Этот нюанс хорошо бы обсудить отдельно.
Не "отдельно", а с него надо начинать.
Потому что если язык вообще позволяет произвольные игры с указателями, типа сохранить после удаления объекта, то нет смысла и запрещать их произвольное создание.
Язык с ManMM это переносимый ассемблер (даже если это C++). Язык с AMM это то, что требует как минимум unsafe-слоя для реализации и связи с нижними слоями.
Попытка их совместить — см. про коня и лань.
S>Вообще неплохо-бы предусмотреть способ указания (в самой программе на кси) для желаемого поведения при конкретном случае (для low level штук).
S>Например чтобы не происходило автоосвобождение большого колличества мелких объектов по отдельности, а пачкой
Это речь про GC. Разные стили GC могут выбираться по реализации, но в этом нет ничего нового.
S>(ещё когда при закрытии приложении ОС сама освобождает выделенную память)
N>>4. Уровень фиксации типизации — статическая, динамическая.
S>Все Три вида типизации: ~ по трём отдельным обработчикам
S>Можно сказать — три диалекта языка.
S> Динамическая типизация ~ ksi-script
S> Строгая типизация ~ ksi-pl
S> динамическая + строгая ~ ksi-lang
Почему это динамическая+строгая?
S>Каждый обработчик может быть как компилятор, так и интерпретатор. А может быть два в одном.
S>Это уже нюанс реализации обработчика.
N>>5. Уровень жёсткости типизации. Например, насколько разрешён integral promotion и по каким правилам.
S>СИ-шных ошибок в проектировании языка желательно избежать!
Только вначале разобраться, что там ошибки, что — последствия ограничений реализации, а что — полезные фишки, облегчающие (обычно) жизнь программисту.
S>Есть шаблонный метод x !as[type] , который вызывается в программе-скрипте явно для преобразования типов.
Всегда? Безопасные (без изменения характера типа и без потери точности) расширения вообще не допускаются?
S>Рассмотрим на примере. Если мы хотим преобразование явного вида из $int в $float тогда в декларативной части:
S>S>$float #allow_actions( conversion_from[$int] )
S>conversion_from[$int].as[$float] = #fn ($int: number) : $float
S>{ #ret = /* какая-то системная функция */ }
S>do = {
S> i = 5
S> f = (i !as[$float])
S>}
S>
Я не понял, к чему '!' впереди "!as". В остальном — понятно на локальном уровне. Но мне кажется, что безусловный запрет расширяющих конверсий это диверсия.
Если нужно, их следует запрещать для определённых контекстов. Но я думаю, это будет редко использоваться.
Кстати, int->float для стандартных int32 и binfloat32 это не расширяющая конверсия, возможна потеря точности.
N>>Подобные элементы синтаксиса обязаны быть жёсткими и безальтернативными!
S>Согласен с этим утверждением. Я не точно сформулировал мысль.
S>Начальные символы для системных штук указываются в конфиге обработчика, а не пользовательского проекта.
S>Или жестко заданы внутри компилятора (это нюанс реализации, да)
Скорее жёстко, тут нечего конфигурировать.
S>#struct — это системная команда.
S>Какой начальный символ для команд, а какой для системных типов лучше подобрать?
S>Я предлагаю для команд #
S>Для типов $
S>Для функций &
А зачем выделять типы и функции? Это необычно.
S>Это просто строчки в конфиге обоаботчика. С другой стороны нужен общепринятый формат)
S>Ключевые слова? keywords — нужны ли они вообще в кси? Если да, то какие?
У меня такое впечатление, что вы их называете командами.
S>Можно сделать bitwise методы для integer types (выглядят как именованные операторы bit_xor, bit_and, bit_shift +1 -1)
Можно.
S>>>Таким образом добавление системных типов не будет конфликтовать с уже написанным пользовательским кодом.
N>>Для такого давно придумали пространства имён. Но редкие конфликты с автоматической переделкой — не проблема.
S>В кси — модули. Хотя пространства имён возможно тоже понадобятся (или нет).
Если хочется чего-то выше уровня песочницы — понадобятся, иерархические.
S>>>* По сути sequence — это как лямбда без параметров.
N>>Только с автозахватом из внешнего контекста? Уточни.
S>Да, с автозахватом (closure)
Если не регулируется — могут жаловаться.
S>Мб добавить возможность задания seq без захвата локального внешнего контекста через конструкцию #{ } ?
Тогда в ней можно и думать писать явный список для захвата.
S>Ключевых слов в кси стараюсь вообще избегать.
Совсем избежать не получится.
Префиксовать все — возможно, есть такие стили, но обычно пользователи жалуются.
S>К примеру можно определить системную функцию &do_while цикл с пост-условием
Есть такие стили, да. Можно посмотреть на Common LISP как образчик. Там макрами транслируется часть конструкций в другой код.
S>Значит нужна возможность задать для структуры как она передаётся ( _by_value или _by_pointer )
Да. И умолчание скорее by value.
N>>Интерфейсы или типажи (traits)? Есть причина вводить новое слово для того же?
S>Нет, это не интерфейсы. Про интерфейсы я ответил выше как #actions
S>Категории ещё могут быть абстрактными (с запретом к привязки для типов)
S>Для специальных значений, или сигналов об ошибке.
Ближе к типажам, наверно.
N>>Вообще обычно говорят более математически — hashable или linearly orderable.
S>Это похоже на набор методов для работы с данными.
S>S>ordering = #enum ( strong weak partial )
S>cmp_result = /* ? */
S>comparable = #actions [ordering: O, $type: left_type right_type] (
S> cmp = #fn_params (left_type: left, right_type: right) : cmp_result
S> (<) = #fn (left_type: left, right_type: right) : $bool
S> { #return( (left !cmp: right) == cmp_result.less ) }
S>)
S>
Ну да, дальше определяется, что например hashable должен поддерживать hash(), а linearly orderable — сравнение как минимум на "меньше" (и полезно на "равно", судя по <=> в новом C++).
S>Стандыртные наборы действий (интерфейсы) для системных типов необходимо определить.
S>Желательно совместными усилиями, а не в одиночку.
N>>Итого
N>>У тебя нет killer feature. Без неё это не выйдет за пределы одного условного диссера.
S>А как-же работа с типами как с обычными значениями?
S>Вместо плюсовых <type_traits> std::is_same_v<> и using type =
По сравнению с плюсами — может быть. По сравнению с более новыми языками — нет.
S>А как же встроенная система атрибутов. Позволяющая в том числе и рефлексию (интроспекцию).
Аналогично.
Глубоко изучи для начала Rust.
S>Возможность добавлять пользовательские конструкции над seq как функции.
S>--
S>Постораюсь ответить на вопросы, которые ещё остались неотвечены.
S>То что я написал — моё приблизительное представление.
S>На основе этого можно же сделать better language, как бы он не назывался
Можно. Но без хорошей теоретической подготовки шансы около нуля.