NUDA
От: Denom Украина  
Дата: 04.04.11 08:57
Оценка: 69 (7)
Доклад по NUDA на конференции ПАВТ 2011:
Здесь

Взято c habrahabr.ru

ссылка в конце статьи
... << RSDN@Home 1.2.0 alpha 4 rev. 1476>>
Re: NUDA
От: _nn_ www.nemerleweb.com
Дата: 04.04.11 09:11
Оценка:
Здравствуйте, Denom, Вы писали:

D>Доклад по NUDA на конференции ПАВТ 2011:

D>Здесь


Интересны проблемы о которых автор говорит в конце доклада.
Это ограничение языка или все же есть решения ?


Кроме того, Nemerle не является идеальным расширяемым языком для высокопроизводительных вычислений.

  • Прежде всего, получение семантической информации внутри макросов затруднено.
    В частности, информация об объявленных переменных и типах выражений становится доступной только в процессе развёртки макросов.
    Если же требуется и получить информацию, и сохранить макросы в дереве исходного кода, требуется использовать обходные пути, которые не всегда работают.

  • Во-вторых, все функции в Nemerle-программе транслируются независимо, и нет возможности получить код одной функции из другой функции.
    Как следствие, реализация преобразований типа встраивания функций или генерации специальных версий функций для определённых наборов параметров затруднены.

  • В-третьих, для инициирования преобразований требуется применять макросы; возможность инициирования преобразований через определённые шаблоны кода отсутствует.
    Соответственно, нет возможности выполнить преобразования, добавляющие новую семантику без добавления синтаксиса — как добавление в язык массивного программирования.

  • Наконец, в языке отсутствует гибкий механизм назначения атрибутов вершинам дерева кода и переменным.

    Всё это говорит о том, что для высокопроизводительных вычислений потребуется разработать более гибкий расширяемый язык программирования.
    Но для этого сначала потребуется попробовать решить при помощи NUDA и Nemerle более широкий круг задач — чтобы определить требования, предъявляемые к новому языку.

  • http://rsdn.nemerleweb.com
    http://nemerleweb.com
    Re[2]: NUDA
    От: hardcase Пират http://nemerle.org
    Дата: 04.04.11 09:50
    Оценка:
    Здравствуйте, _nn_, Вы писали:

    __>Здравствуйте, Denom, Вы писали:


    D>>Доклад по NUDA на конференции ПАВТ 2011:

    D>>Здесь


    __>Интересны проблемы о которых автор говорит в конце доклада.

    __>Это ограничение языка или все же есть решения ?

    Автор вполне объективен. Но этим ограничениям можно положить конец просто свинтив бошку стандартному парсеру — т.е. сделать подключаемый парсер на PEG-е. В этом случае Nemerle будет просто бэкэндом, в котором можно использовать уже существующую кодовую базу (она всетаки немалая).
    /* иЗвиНите зА неРовнЫй поЧерК */
    Re[3]: NUDA
    От: Ziaw Россия  
    Дата: 04.04.11 14:31
    Оценка:
    Здравствуйте, hardcase, Вы писали:

    H>Автор вполне объективен. Но этим ограничениям можно положить конец просто свинтив бошку стандартному парсеру — т.е. сделать подключаемый парсер на PEG-е. В этом случае Nemerle будет просто бэкэндом, в котором можно использовать уже существующую кодовую базу (она всетаки немалая).


    Описанные проблемы одним парсером не решаются. Например преобразование через шаблоны кода, хотя это очень спорная фича. А вот метаинформация для узлов AST точно не помешает.
    Re: NUDA
    От: Аноним  
    Дата: 04.04.11 17:29
    Оценка:
    Впечатлен.
    Re[2]: NUDA
    От: Аноним  
    Дата: 04.04.11 17:36
    Оценка:
    на сколько реально поправить недостатки?
    (не призываю это делать, просто интересуюсь насколько возможно это сделать)
    Re[2]: NUDA
    От: VladD2 Российская Империя www.nemerle.org
    Дата: 04.04.11 17:46
    Оценка: 1 (1)
    Здравствуйте, _nn_, Вы писали:

    __>Интересны проблемы о которых автор говорит в конце доклада.

    __>Это ограничение языка или все же есть решения ?

    Скажем так — трудности есть, но их можно обойти.

    __>Кроме того, Nemerle не является идеальным расширяемым языком для высокопроизводительных вычислений.


    Интересно, а кто является? На мой взгляд до N2 таковых не было и вряд ли появится.

    __>* Прежде всего, получение семантической информации внутри макросов затруднено.

    __>В частности, информация об объявленных переменных и типах выражений становится доступной только в процессе развёртки макросов.
    __>Если же требуется и получить информацию, и сохранить макросы в дереве исходного кода, требуется использовать обходные пути, которые не всегда работают.

    Тут трудно что-то конкретно сказать. Обходные пути есть и они работают. Что автор имел под "не всегда" я не знаю.

    Обходных путей несколько:
    1. Если нужно дождаться появления одного типа (или небольшого их количества), то использовать методы typer.TypeExpr() и typer.DelayMacro(). Например, этот метод используется в реализации макроса foreach.
    2. Если нужно работать с нераскрытыми макросами но при этом анализировать типы (обычно это нужно при массовой генерации кода, как например, в случае с макросом реализующим linq), то лучше использовать методом typer.TransformWhenAllTypesWouldBeInfered() в сочетании все с тем же typer.TypeExpr(). TransformWhenAllTypesWouldBeInfered позволяет дождаться когда код метода будет полностью типизирован. При этом будет доступно PExpr. Причем в его свойстве TypedObject будет содержаться соответствующая ветка типизированного AST (обычно TExpr).
    3. Запомнить ссылку на PExpr являющийся телом метода и вызвать типизацию тела метода вручную. При этом типизация будет произведена дважды, но за-то будет полный контроль над происходящим. Как и в случае пункта 2, после окончания типизации тела метода в прикопаном PExpr будут доступны свойства TypedObject.

    Подозреваю, что автор просто не был знаком с этими подходами. По крайней мере с последними двумя.

    Собственно это все довольно сложно и в N2 я планировал упростить это дело.

    __>* Во-вторых, все функции в Nemerle-программе транслируются независимо, и нет возможности получить код одной функции из другой функции.


    Так и есть. И по другому было бы сложно сделать.

    __>Как следствие, реализация преобразований типа встраивания функций или генерации специальных версий функций для определённых наборов параметров затруднены.


    Они просто должны делаться на других стадиях компиляции. Не сложно расширить компилятор позволив прикладному программисту вводить свои обработчики работающие на последних стадиях типизации.

    __>* В-третьих, для инициирования преобразований требуется применять макросы; возможность инициирования преобразований через определённые шаблоны кода отсутствует.


    Есть такое. Подобные преобразования опят таки лучше осуществлять на поздних стадиях типизации. Это уже не макросы понимании Немерла. Это некие оптимизаторы. Короче, см. выше.

    __>Соответственно, нет возможности выполнить преобразования, добавляющие новую семантику без добавления синтаксиса — как добавление в язык массивного программирования.


    Не уверен, что это вообще хорошая идея — менять семантику без введения нового синтаксиса. Так можно запутать программистов. В прочем, если речь идет об оптимизациях (как говорилось выше), то опять же см. выше.

    __>* Наконец, в языке отсутствует гибкий механизм назначения атрибутов вершинам дерева кода и переменным.


    Вообще не понял о чем идет речь.

    __>Всё это говорит о том, что для высокопроизводительных вычислений потребуется разработать более гибкий расширяемый язык программирования.


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

    Собственно, если автор хочет, то пока не поздно примкнуть к его проектированию или хотя бы описать свои требования более детально.

    __>Но для этого сначала потребуется попробовать решить при помощи NUDA и Nemerle более широкий круг задач — чтобы определить требования, предъявляемые к новому языку.


    Само собой. Но автор вроде этим и занимался.
    Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
    Re[4]: NUDA
    От: VladD2 Российская Империя www.nemerle.org
    Дата: 04.04.11 17:49
    Оценка:
    Здравствуйте, Ziaw, Вы писали:

    Z>Например преобразование через шаблоны кода, хотя это очень спорная фича.


    Если без изменения семантики, то это просто оптимизация. Пусть и определяемая пользователем. Это как раз не так сложно сделать.

    Z>А вот метаинформация для узлов AST точно не помешает.


    О чем идет речь? Вы бы хоть показали пример того что имеете в виду.
    Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
    Re[3]: NUDA
    От: Аноним  
    Дата: 04.04.11 17:59
    Оценка:
    Оптимизация (трансформации кода) по нормальному должны определяться без изменения синтаксиса.
    Нечто вроде expand(a*(b+c)==a*b+a*c)
    а потом применять просто к выражению expand.....
    Re[4]: NUDA
    От: VladD2 Российская Империя www.nemerle.org
    Дата: 04.04.11 18:21
    Оценка:
    Здравствуйте, Аноним, Вы писали:

    А>Оптимизация (трансформации кода) по нормальному должны определяться без изменения синтаксиса.


    Оптимизация и трансформация — это разные вещи, так как трансформация включает нечто большее.
    Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
    Re[3]: NUDA
    От: VladD2 Российская Империя www.nemerle.org
    Дата: 04.04.11 20:26
    Оценка:
    Здравствуйте, Аноним, Вы писали:

    А>на сколько реально поправить недостатки?

    А>(не призываю это делать, просто интересуюсь насколько возможно это сделать)

    http://www.rsdn.ru/forum/nemerle/4221211.1.aspx
    Автор: VladD2
    Дата: 04.04.11
    Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
    Re[5]: NUDA
    От: catbert  
    Дата: 05.04.11 19:19
    Оценка:
    Здравствуйте, VladD2, Вы писали:

    VD>О чем идет речь? Вы бы хоть показали пример того что имеете в виду.


    Мне кажется, это UserData для PExpr-ов
    Re[6]: NUDA
    От: hardcase Пират http://nemerle.org
    Дата: 05.04.11 20:28
    Оценка:
    Здравствуйте, catbert, Вы писали:

    C>Мне кажется, это UserData для PExpr-ов


    Велика вероятность того, что PExpr будет заменен совсем другим PExpr-ом.
    /* иЗвиНите зА неРовнЫй поЧерК */
    Re[6]: NUDA
    От: VladD2 Российская Империя www.nemerle.org
    Дата: 05.04.11 20:47
    Оценка:
    Здравствуйте, catbert, Вы писали:

    VD>>О чем идет речь? Вы бы хоть показали пример того что имеете в виду.


    C>Мне кажется, это UserData для PExpr-ов


    А может об кастом-атрибутах для выражений. Иди догадайся!
    Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
    Re: NUDA
    От: adinetz  
    Дата: 08.04.11 14:08
    Оценка:
    Итак, постараюсь уточнить и конкретизировать пожелания:

    1) Работа с кодом одной функции из другой функции

    Где это можне понадобиться — встраивание (inline) функций. Например:


    
    inline f(i: int) : int {
      ... 
    }
    
    g() : void {
      // ... 
      a = f(i); // требуется заинлайнить функцию f
      // ... 
    }


    В функции g() нужно заинлайнить вызов функции f(), для этого в момент вызова макроса (или другого механизма, при помощи которого выполняется инлайн), требуется иметь код (в виде PExpr) функции f. Этот код извлекается при помощи макроса-атрибута inline, применяемого к f(). И если сначала работает этот макрос, а потом делается инлайн функции f() в функции g() — всё хорошо. Если наоборот — насколько я понимаю, сейчас нет возможности явно дёрнуть этот макрос. Насколько я понимаю, это можно добавить — надо разрешить одновременную трансляцию нескольких функций + флажок, оттранслирована ли уже функция.

    Кстати, может трансляция одной функции (как f) несколько раз. Например, для функции указано, что у неё на этапе компиляции генерируются разные версии для константных значений какого-либо параметра. Тогда новую версию надо генерировать всякий раз, когда встречается новое значение константного параметра (понимаю, катится в сторону C++). Или ещё пример: функция может быть использована на ГПУ, и требуется сгенерировать для неё OpenCL-код, но только в том случае, когда она используется в какой-то другой функции, для которой уже генерируется OpenCL-код. Сейчас это решается требованием пометить все такие функции макросом nucode, но ведь мы хотим упросить жизнь программистам и не перегружать их лишними аннотациями ?

    2) Навешивание атрибутов на объекты языка (выражения, члены типов, переменные)

    Простейший способ это сделать руками — завести глобальный словарь вида (объект, имя атрибута) -> (значение), сейчас так и делаю. Какие с этим возникают проблемы:
    — как в такой системе прикреплять атрибуты к локальным переменным? Это основная проблема. Объект Name() однозначно переменную не идентифицирует, объект LocalValue() не сохраняется, если типизация выполняется дважды. А сейчас она как раз выполняется дважды, один раз вручную, один раз — ожиданием, пока будут протипизированы все выражения
    — как наследовать атрибуты выражения, если оно подаётся на вход макросу, а на выход подаётся другое? Вот это проблема не техническая, скорее всего, здесь нет простого решения
    — наконец, возникает слишком много объектов, для которых можно получать атрибуты. Т.е. имя может быть локальной переменной, членом типа, к члену типа может быть обращение по полному/сокращённому имени, через this/base и т.д. Везде атрибуты приходится получать по-разному. Хотелось бы иметь более унифицированный механизм, как это делать

    3) Доступ к семантической информации на этапе компиляции макросов

    Прежде всего это А) типы выражений Б) объекты (переменные, члены класса и т.д.), сопоставленные именам. Если к типам доступ кое-как есть (и с ним становится значительно труднее, если начинается раскрытие макросов вручную), то с переменными совсем плохо. Например, задача: заменить все вхождения переменной i в выражение на константу (или другое выражение). И если будет переменная в более вложенной области с тем же именем, например:

    a = i;  // надо заменить i
    for(j = 0; j < n; j++) {
      mutable i = 2;  // не надо заменять
      b = i;  // не надо заменять
    }


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

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

    4) Более гибкие механизмы обращения к расширению (макросу) — здесь несколько вариантов:

    А) применение макроса к более широкому выражению, нежели то, к которому он применяется синтаксически. Например, есть переменная-массив, нужно в этом массиве поменять порядок индексов (для более быстрой работы с памятью). Синтаксически это выглядит, например, так:

    permut(2, 1) def a = array(m, n) : array[2, float]; // объявление + перестановка индексов
    // ...
    // использование переменной a
    // ...


    Т.е. непосредственным аргументом макроса является только объявление переменной a, в то время как реально на вход по-хорошему должны подаваться все последующие выражения, т.к. в них тоже нужно внести изменения, как минимум — поменять там порядок индексов при обращении к этому массиву, чтобы код работал правильно. Ровно поэтому сейчас сложно писать какие-то нетривиальные макросы, применяемые вот так к переменным.

    Б) макрос как обычный член класса (вызов метода, обращение к полю, оператор и т.д.). При вызове такого "члена" на самом деле срабатывает макрос, и код этого макроса подставляется на место вызова этого самого члена. Так можно организовать инлайн функций или генерацию специальных версий тела функции для определённых значений параметров (см. пункт 1).

    В) макрос, который генерирует "член" класса (реально это будет, скорее всего, external-метод), если этот член не определён. Здесь можно привести несколько примеров. Первый: прокси-класс, который реально перенаправляет обращения к полям/методам к другому классу. Второй: класс, поля которого — константы, соответствующие римским цифрам (этот пример вроде очень любят в Ruby). Наконец, третий пример, более реальный: в OpenCL есть векторные типы фиксированной длины. Например, int8 — вектор длины 8 из данных типа int. У них есть специальная операция swizzle, т.е. у вектора можно получить любую перестановку значений его полей. Например, если i — типа int8, то можно написать: i.s1s1s3s3s5s4s7s6, и так для любой комбинации полей вектора. Если для 4-х все комбинации ещё можно сгенерировать статически, то для 8 и 16 это невозможно. Соответственно, можно придумать макрос, который вот такие вот комбинации будет обрабатывать и генерировать динамически.

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

    5) Управление порядком раскрытия макросов. Например, "не раскрывать макросы if/for/while, раскрывать все остальные". Сейчас я это делаю руками (нарушая попутно инкапсуляцию некоторых методов), думаю, уместнее бы такой функциональности быть в самом языке.

    Ну и по мелочам:



    D>Доклад по NUDA на конференции ПАВТ 2011:

    D>Здесь

    D>Взято c habrahabr.ru


    D>ссылка в конце статьи
    Re[2]: NUDA
    От: VladD2 Российская Империя www.nemerle.org
    Дата: 08.04.11 16:49
    Оценка:
    Здравствуйте, adinetz, Вы писали:

    A>Итак, постараюсь уточнить и конкретизировать пожелания:


    A>1) Работа с кодом одной функции из другой функции


    Функции принципиально типизируются в неопределенном порядке. Более того под управлением IDE типизация может быть неоднократной. Так что попытки лезть из одной функции в другую принципиально опасны.

    Лучше поступать по другому. Есть как минимум два варианта:
    1. Вручную типизировать функции в макро-атрибуте работающем на стадии WithTypedMembers. Пример этого подхода можно наблюдать здесь. Поясню код комментариями:
          def convertMethod(name : string, meth : MethodBuilder, isDependent = true) : PExpr
          {
            #region Type method body
            // Запоминаем нетипизированное тело метода (т.е. его PExpr)
            def body = meth.Body;
            def oldEmitDebug = typer.Manager.Options.EmitDebug; 
            typer.Manager.Options.EmitDebug = false; // выключаем генерацию отладочной информации чтобы упростить анализ
            def methodTyper = Typer(tb, null, meth, meth.Env); // создаем тайпер который может типзиировать тело метода
            methodTyper.RunFullTyping(); // запускает типизацию тела метода (вручную)
            typer.Manager.Options.EmitDebug = oldEmitDebug; // восстанавливает настройку генерации отладочной информации
            #endregion
    
            // Обрабатывает body как нам нужно. В body к этому моменту находится PExpr 
            // у которого (и у все подвыражений) в свойстве TypedObject находится ссылка 
            // типизированно выражение (TExpr, TParametr и т.п.).
    
            // Восстанавливаем тело метода в нетипизированное выражение.
            // Здесь можно поместить новое тело (измененное). Важно только чтобы в исходном теле не было ошибок.
            meth.Body = body;


    A>Где это можне понадобиться — встраивание (inline) функций.


    Локальные функции и так автоматом инлайнятся при соблюдении некоторых условий. Условия следующие:
    1. Функция должна быть объявлена в том же блоке кода где она используется. В 2.0 это ограничение постараемся устранить.
    2. Функция не должна использоваться как первоклассное значение.
    3. Функция должна вызваться ровно один раз. В принципе это ограничение и можно устранить введением некой пометки функции.


    A>
    A>inline f(i: int) : int {
    A>  ... 
    A>}
    
    A>g() : void {
    A>  // ... 
    A>  a = f(i); // требуется заинлайнить функцию f
    A>  // ... 
    A>}
    A>


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

    В Nemerle 2.0 постараемся ввести специальную стадию на которой будет не сложно делать подобные преобразования.

    A>В функции g() нужно заинлайнить вызов функции f(), для этого в момент вызова макроса (или другого механизма, при помощи которого выполняется инлайн), требуется иметь код (в виде PExpr) функции f. Этот код извлекается при помощи макроса-атрибута inline, применяемого к f(). И если сначала работает этот макрос, а потом делается инлайн функции f() в функции g() — всё хорошо. Если наоборот — насколько я понимаю, сейчас нет возможности явно дёрнуть этот макрос. Насколько я понимаю, это можно добавить — надо разрешить одновременную трансляцию нескольких функций + флажок, оттранслирована ли уже функция.


    Если есть такая необходимость, то можно связаться со мной по скайпу, и я постараюсь раяснить детали того как это можно сделать.

    A>Кстати, может трансляция одной функции (как f) несколько раз. Например, для функции указано, что у неё на этапе компиляции генерируются разные версии для константных значений какого-либо параметра. Тогда новую версию надо генерировать всякий раз, когда встречается новое значение константного параметра (понимаю, катится в сторону C++). Или ещё пример: функция может быть использована на ГПУ, и требуется сгенерировать для неё OpenCL-код, но только в том случае, когда она используется в какой-то другой функции, для которой уже генерируется OpenCL-код. Сейчас это решается требованием пометить все такие функции макросом nucode, но ведь мы хотим упросить жизнь программистам и не перегружать их лишними аннотациями ?


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

    A>2) Навешивание атрибутов на объекты языка (выражения, члены типов, переменные)


    A>Простейший способ это сделать руками — завести глобальный словарь вида (объект, имя атрибута) -> (значение), сейчас так и делаю. Какие с этим возникают проблемы:

    A>- как в такой системе прикреплять атрибуты к локальным переменным? Это основная проблема. Объект Name() однозначно переменную не идентифицирует, объект LocalValue() не сохраняется, если типизация выполняется дважды. А сейчас она как раз выполняется дважды, один раз вручную, один раз — ожиданием, пока будут протипизированы все выражения
    A>- как наследовать атрибуты выражения, если оно подаётся на вход макросу, а на выход подаётся другое? Вот это проблема не техническая, скорее всего, здесь нет простого решения
    A>- наконец, возникает слишком много объектов, для которых можно получать атрибуты. Т.е. имя может быть локальной переменной, членом типа, к члену типа может быть обращение по полному/сокращённому имени, через this/base и т.д. Везде атрибуты приходится получать по-разному. Хотелось бы иметь более унифицированный механизм, как это делать

    Достаточно будет если для PExpr и TExpr завести поле UserData типа "словарь", как это сейчас сделано для TypeBuilder.

    A>3) Доступ к семантической информации на этапе компиляции макросов


    A> Прежде всего это А) типы выражений Б) объекты (переменные, члены класса и т.д.), сопоставленные именам. Если к типам доступ кое-как есть (и с ним становится значительно труднее, если начинается раскрытие макросов вручную), то с переменными совсем плохо. Например, задача: заменить все вхождения переменной i в выражение на константу (или другое выражение).


    Тут проблема в том, что макросы как раз эту семантику и строят. По этому мы не можем производить типизацию до раскрытия макросов. Однако доступна двупроходная схема. Сначала типизируем выражение как есть (со стандартным раскрытием макросов), а потом анализируем что получилось и заменяем на что-то другое. Единственное ограничение — первый проход должен быть удачным (не должен приводить к ошибкам типизации).

    Однако подобные замены вообще лучше осуществлять на поздних стадиях, когда происходит обработка типизированного представления. В компиляторе эти стадии называются шаги T2-T4. Можно сделать не сложную плагинную систему позволяющую вставлять свои шаги преобразования типизированного АСТ между этими стадиями. Это не сложно и можно сделать уже сейчас.

    A>И если будет переменная в более вложенной области с тем же именем, например:


    A>Проблемы эти возникают ещё и от того, что сейчас в Немерле процессы раскрытия макросов и типизации совмещены. В принципе, можно было бы их разнести, и по крайней мере часть макросов раскрывать после полной типизации.


    Это невозможно. Компилятор не знает что делат макрос и как интерпретировать код содержащий макросы. По сему типизировать макросы он не может. Я уже объяснил выше то как можно это обойти.

    A>Похожим образом процесс организован, например, в xoc, расширяемом компиляторе языка C.


    А можно в двух словах о том, что такого интересного есть в этом xoc-е? А то читать 110 страниц как-то в лом.

    A>4) Более гибкие механизмы обращения к расширению (макросу) — здесь несколько вариантов:


    A> А) применение макроса к более широкому выражению, нежели то, к которому он применяется синтаксически. Например, есть переменная-массив, нужно в этом массиве поменять порядок индексов (для более быстрой работы с памятью). Синтаксически это выглядит, например, так:


    A>
    A>permut(2, 1) def a = array(m, n) : array[2, float]; // объявление + перестановка индексов
    A>// ...
    A>// использование переменной a
    A>// ...
    A>


    A>Т.е. непосредственным аргументом макроса является только объявление переменной a, в то время как реально на вход по-хорошему должны подаваться все последующие выражения, т.к. в них тоже нужно внести изменения, как минимум — поменять там порядок индексов при обращении к этому массиву, чтобы код работал правильно. Ровно поэтому сейчас сложно писать какие-то нетривиальные макросы, применяемые вот так к переменным.


    Ну, то есть сделать макрос вида:
    macro Permut(a : int, b : int, exprs : list[PExpr])
      syntax ("permut", "(", a, ")", exprs)
    {
      ...
    }

    Который позволит захватывать выражения идущие от permut и до конца текущего блока?

    Это только в Nemerle 2.0.

    В прочем еще не ясно, что делать с подобными случаями:
    [/Nemerle]
    permut(2, 1) def a = array(m, n) : array[2, float];
    ...
    permut(2, 1) def b = array(m, n) : array[2, float];
    ...
    [/Nemerle]
    По этой логике второй permut окажется вложенным в "exprs" первого. Это нормально?

    A> Б) макрос как обычный член класса (вызов метода, обращение к полю, оператор и т.д.). При вызове такого "члена" на самом деле срабатывает макрос, и код этого макроса подставляется на место вызова этого самого члена. Так можно организовать инлайн функций или генерацию специальных версий тела функции для определённых значений параметров (см. пункт 1).


    Мы обдумывали "макросы-расширения". Тут основная сложность заключается в том, что методы могут быть перегружены (да и другие члены в некоторых случаях тоже). Получится неоднозначность. Для ее разрешения сначала надо будет типизировать выражение так как-будто макрос-расширение это обычный метод (иди другой член), а уже потом заменить обращение к нему на макрос. В общем-то это возможно, но определение такого макроса будет несколько запутанным, так как по сути придется сначала объявить метод-расширение, а потом привязать к нему макрос который будет подставляться вместо этого метода (после того как будет разрешена ссылка на метод). Например, это можно оформить вот так:
    macro Where[T](this source : Seq[T], predibate : T -> bool) : Seq[T]
    {
      ...
      // генерируем код который должен быть обязательно совместим с типами выражений передаваемых в качестве параметров и с типом возвращаемого значения (допустима ко/контр-вариантность).
    }

    Естественно, что такому макросу уже нельзя будет будет передать на вход выражения типы которых не совместимы с указанными. Зато внутри они смогут сразу использовать информацию о типах и подставлять любые специализации.

    Фактически это нечто похожее на шаблоны С++ только их код можно генерировать программно.

    A> В) макрос, который генерирует "член" класса (реально это будет, скорее всего, external-метод), если этот член не определён.


    Ничего не понял.

    A>Здесь можно привести несколько примеров. Первый: прокси-класс, который реально перенаправляет обращения к полям/методам к другому классу.


    Это уже есть и работает.

    A> Второй: класс, поля которого — константы, соответствующие римским цифрам (этот пример вроде очень любят в Ruby).


    А можно хотя бы псевдо-код?

    A>Наконец, третий пример, более реальный: в OpenCL есть векторные типы фиксированной длины. Например, int8 — вектор длины 8 из данных типа int. У них есть специальная операция swizzle, т.е. у вектора можно получить любую перестановку значений его полей. Например, если i — типа int8, то можно написать: i.s1s1s3s3s5s4s7s6, и так для любой комбинации полей вектора. Если для 4-х все комбинации ещё можно сгенерировать статически, то для 8 и 16 это невозможно. Соответственно, можно придумать макрос, который вот такие вот комбинации будет обрабатывать и генерировать динамически.


    Что мешает это делать сейчас?

    A> Г) Вызов макроса/расширения по произвольному паттерну.


    Это то что я описал выше? Или имеется в виду что-то иное?

    A> Самый общий вариант, через него можно реализовывать другие. По сути, в этом случае получается система правил и стратегий преобразования, что-то типа языка Stratego. С помощью такого инструмента можно будет добавить в язык массивное программирование.


    Опять же, можно примеры псевдокода?

    A>5) Управление порядком раскрытия макросов. Например, "не раскрывать макросы if/for/while, раскрывать все остальные". Сейчас я это делаю руками (нарушая попутно инкапсуляцию некоторых методов), думаю, уместнее бы такой функциональности быть в самом языке.


    А какова цель этого? Сдается мне, что все это подпадает под подход описанный мною в самом начале моего ответа.

    A>Ну и по мелочам:


    A>* Можно ли при помощи макросов генерировать большое количество всякого using <что-то>?


    Или я не понял вопроса, или ответ — да. Какая разница сколько и чего генерировать?


    A>* Зачем при квазицитировании явно писать $(i:name), $(i:int) и т.д., ведь тип подставляемого объекта уже известен?


    Типы вычисляются только при типизации. А работа а АСТ ведется раньше. Паттерны (квази-цитаты относятся именно к ним), так вообще с типизацией дело не имеют. Это чисто синтаксическая фича. Потому, и приходится эту информацию брать у пользователя.

    A>* Хотелось бы иметь стандартное функции проверки PExpr на одинаковость.


    А чем не удовлетворяет Equals?

    A>И было бы ещё лучше, если бы её можно было вызывать, просто несколько раз используя переменную в паттерне


    Как в Хаскеле? Да идея хорошая, то но относящаяся к макросам. Постараемся реализовать в Н2.

    A>* На мой взгляд вещи типа += и т.д. обрабатываются как-то уж слишком запутанно


    В смысле?

    A>* Есть/будет ли возможность задавать приоритет макросов или макроопераций?


    Я не знаю что такое операции. Но приоритеты для макросов верхнего уровня будут в Н2. Цель — позволить описать последовательность раскрытия макросов одного уровня, так чтобы одни могли пользоваться результатами других. Речь была об этом?

    A>* Будет ли дерево кода становиться более однородным, т.е. будут ли всякие MatchCase и проч. сливаться с PExpr?


    А что это может дать?
    Планируется слить PExpr и TExpr. На начальных стадиях типизации (где используются макросы) их PExpr будет доступна информация о типах (по мере ее появления). Так же АСТ (в том числе и PExpr) станет неизменяемым. Так что можно будет спокойно хранить на него ссылки.

    A>* Иногда хочется вставлять список выражений не как { ..$es }, а с дополнительными выражениями вокруг, например

    A>
    A>{ mutable a = 5; ..$es; ..$es1 a; }
    A>


    Это возможно и сейчас. Вот здесь находится незамысловатая функция (PrepandExprs) которая делает нечто подобное. А здесь и здесь ее применения. Общая идея очень проста. Берем имеющийся блок и вставляем в его начало свой код.

    A>Планируется ли такая конструкция? Она помогла бы значительно сократить число скобок


    Скобки она не уменьшила бы. Но постараемся упростить работу со списком выражений. Но это уже только в Н2.

    A>* Планируется ли давать макросам доступ к строкам комментариев? Например, есть макрос, который присваивает переменной значение из командной строки — он же может использоваться для генерации текста "usage: ...", который составлять из комментариев


    Что-то я этого вообще не понял. Генерировать комментарии что ли? А кто их увидит то?

    A>* Сейчас нет возможности передавать расширениям параметры командной строки ncc. Планируется ли такая возможность?


    Кто такие расширения? А получить значение командной строки как раз таки можно. Выше я привел пример такого код см. typer.Manager.Options.EmitDebug. Это и есть доступ к параметрам командной строки.
    Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
    Re: NUDA
    От: Muxa  
    Дата: 07.05.11 08:46
    Оценка:
    а как можно принять участие в проекте NUDA?
    опыт:
    CUDA — года 2-3
    на тек. месте работы буду писать на OpenCL
    Nemerle — только видел
    есть шансы?
    Re[2]: NUDA
    От: Denom Украина  
    Дата: 07.05.11 08:56
    Оценка:
    Здравствуйте, Muxa, Вы писали:

    M>а как можно принять участие в проекте NUDA?

    M>опыт:
    M>CUDA — года 2-3
    M>на тек. месте работы буду писать на OpenCL
    M>Nemerle — только видел
    M>есть шансы?
    Я не знаю. Проект на sourceforge
    Спишитесь с авторором.
    В nemerle разобаться можно по ходу дела — материалов хватает
    ... << RSDN@Home 1.2.0 alpha 4 rev. 1476>>
     
    Подождите ...
    Wait...
    Пока на собственное сообщение не было ответов, его можно удалить.