Re[2]: [почти offtop]
От: CodingUnit Россия  
Дата: 04.02.12 10:22
Оценка: -6 :))) :)))
Здравствуйте, Alexey F, Вы писали:

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


CU>>Тьюринг полны это ты погорячился, по определению "В теории вычислимости исполнитель (множество вычисляющих элементов) называется тьюринг-полным, если на нём можно реализовать любую вычислимую функцию", можно ли на шаблонах реализовать любую? Мы пришли к выводу что нет.

AF>Можно поподробнее выделенное? Или здесь имеется ввиду ограничение на число рекурсивно вложенных инстанциаций шаблона?

Я разве сказал что то об инстанционировании шаблона? Я сказал что на шаблонах нельзя написать любую программу в терминах Тьюринга, то есть нельзя писать в файлы, читать, выводить на экран, все что есть это какие то ограниченные прагма директивы конкретного компилятора, короче говоря на них нельзя написать программу любой сложности как на самом С++, C# и Nemerle потому что шаблоны не Тьюринг полны. Выкрутасы которые на них делают оперируя с определениями типов, не то на что расчитаны сами шаблоны, поэтому и компиляторы не все поддерживают эти функции, и скорее более хак чем родная функция, как и на макросах C можно сделать многое что на них никто не собирался изначально делать. Но это некачественное решение на фоне существующих систем метапрограммирования.
Доказательство полноты.
От: WolfHound  
Дата: 06.02.12 09:31
Оценка: 20 (5)
Здравствуйте, CodingUnit, Вы писали:

#include <iostream>

template<class H, class T>
struct TypeList
{
    typedef H Head;
    typedef T Tail;
};
struct NullType{};

template<int ValueArg>
struct I2T
{
    enum { Value = ValueArg };
};

template<class TapeArg>
struct MoveLeftImpl;
template<class TapeArg>
struct MoveRightImpl;

template<class LeftItemsArg, class ItemArg, class RightItemsArg, class DefaultArg>
struct Tape
{
    typedef LeftItemsArg  LeftItems;
    typedef ItemArg       Item;
    typedef RightItemsArg RightItems;
    typedef DefaultArg    Default;
    typedef Tape<LeftItemsArg, ItemArg, RightItemsArg, DefaultArg> This;

    template<class NewItemArg>
    struct Replace
    {
        typedef Tape<LeftItems, NewItemArg, RightItems, Default> Value;
    };

    typedef typename MoveLeftImpl<This>::Value  MoveLeft;
    typedef typename MoveRightImpl<This>::Value MoveRight;
    typedef This                                MoveNone;
};

template<class ItemsArg, class DefaultItemArg>
struct PopItem;

template<class ItemArg, class TailArg, class DefaultItemArg>
struct PopItem<TypeList<ItemArg, TailArg>, DefaultItemArg>
{
    typedef ItemArg Item;
    typedef TailArg Items;
};

template<class DefaultItemArg>
struct PopItem<NullType, DefaultItemArg>
{
    typedef DefaultItemArg Item;
    typedef NullType       Items;
};

template<class ItemArg, class ItemsArg, class DefaultItemArg>
struct PushItem
{
    typedef TypeList<ItemArg, ItemsArg> Value;
};

template<class ItemArg>
struct PushItem<ItemArg, NullType, ItemArg>
{
    typedef NullType Value;
};

template<class TapeArg>
struct MoveLeftImpl
{
    typedef PopItem<typename TapeArg::LeftItems, typename TapeArg::Default> NewLeftItems;
    typedef Tape
        < typename NewLeftItems::Items
        , typename NewLeftItems::Item
        , typename PushItem<typename TapeArg::Item, typename TapeArg::RightItems, typename TapeArg::Default>::Value
        , typename TapeArg::Default
        > Value;
};

template<class TapeArg>
struct MoveRightImpl
{
    typedef PopItem<typename TapeArg::RightItems, typename TapeArg::Default> NewRightItems;
    typedef Tape
        < typename PushItem<typename TapeArg::Item, typename TapeArg::LeftItems, typename TapeArg::Default>::Value
        , typename NewRightItems::Item
        , typename NewRightItems::Items
        , typename TapeArg::Default
        > Value;
};

#define TMCOMMAND(NameArg, StateArg, ItemArg, MoveArg, NewStateArg, NewItemArg)\
template<class LeftListArg, class RightListArg>\
struct NameArg<Tape<LeftListArg, I2T<ItemArg>, RightListArg, I2T<0> >, I2T<StateArg> >\
{\
    typedef I2T<NewStateArg> NewState;\
    typedef typename Tape<LeftListArg, I2T<ItemArg>, RightListArg, I2T<0> >::Replace<I2T<NewItemArg> >::Value::Move##MoveArg NewTape;\
}\
//edn macro

template<template<class, class> class ProgramArg, class TapeArg, class StateArg, class EndStateArg>
struct RunTM
{
    typedef ProgramArg<TapeArg, StateArg> NewSate;
    typedef typename RunTM<ProgramArg, typename NewSate::NewTape, typename NewSate::NewState, EndStateArg>::Value Value;
};

template<template<class, class> class ProgramArg, class TapeArg, class EndStateArg>
struct RunTM<ProgramArg, TapeArg, EndStateArg, EndStateArg>
{
    typedef TapeArg Value;
};


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


typedef Tape<NullType, I2T<0>, NullType, I2T<0>> Tape1;
typedef Tape1::MoveRight Tape2;
typedef Tape2::Replace<char>::Value Tape3;
typedef Tape3::MoveRight Tape4;
typedef Tape4::MoveRight Tape5;
typedef Tape5::MoveLeft Tape6;
typedef Tape6::MoveLeft Tape7;
typedef Tape7::MoveLeft Tape8;
typedef Tape8::MoveRight Tape9;

template<class TapeArg, class StateArg>
struct MyProgram;
TMCOMMAND(MyProgram, 0, 0, Left, 1, 1);
TMCOMMAND(MyProgram, 1, 0, Left, 2, 2);
TMCOMMAND(MyProgram, 2, 0, Left, 3, 3);
TMCOMMAND(MyProgram, 3, 0, Left, 4, 4);

int main(int argc, char* argv[])
{
    std::cout << typeid(RunTM<MyProgram, Tape1, I2T<2>, I2T<4> >::Value).name() << std::endl;
    std::cout << std::endl;
    std::cout << typeid(Tape1).name() << std::endl;
    std::cout << typeid(Tape2).name() << std::endl;
    std::cout << typeid(Tape3).name() << std::endl;
    std::cout << typeid(Tape4).name() << std::endl;
    std::cout << typeid(Tape5).name() << std::endl;
    std::cout << typeid(Tape6).name() << std::endl;
    std::cout << typeid(Tape7).name() << std::endl;
    std::cout << typeid(Tape8).name() << std::endl;
    std::cout << typeid(Tape9).name() << std::endl;
    return 0;
}
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[3]: [почти offtop]
От: catbert  
Дата: 04.02.12 10:29
Оценка: 1 (1) +4
Здравствуйте, CodingUnit, Вы писали:

CU>Я разве сказал что то об инстанционировании шаблона? Я сказал что на шаблонах нельзя написать любую программу в терминах Тьюринга, то есть нельзя писать в файлы, читать, выводить на экран, все что есть это какие то ограниченные прагма директивы конкретного компилятора, короче говоря на них нельзя написать программу любой сложности как на самом С++, C# и Nemerle потому что шаблоны не Тьюринг полны.


Тут Тюринг ни при чем он про рисование на экране не говорил.
Re[9]: [почти offtop]
От: WolfHound  
Дата: 06.02.12 08:39
Оценка: 2 (2) +2
Здравствуйте, VladD2, Вы писали:

VD>Команд может и достаточно, но у любой реализации брэйнфака конечный объем даных, а это уже нарушает условие машины тьюринга имеющей на входе потенциально бесконечный поток данных. Так что пример реализации брэйнфака никак не доказывает тюринг-полноты.

Я тебе уже несколько раз сказал, что если следовать этой логике, то Тьюринг полных вычислителей в природе не существует.
Доказательством полноты по Тьюрингу является создание интерпретатора машины Тьюринга.
При этом всегда делается вид, что у вычислителя бесконечная память.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[10]: [почти offtop]
От: Lloyd Россия  
Дата: 05.02.12 14:11
Оценка: 4 (3)
Здравствуйте, VladD2, Вы писали:

L>>Минус объяснишь, или просто не с той ноги встал?


VD>К переходу на личности мое замечание отношения не имеет,


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

VD>но развивать тему я не хочу.


Ну еще бы ты хотел.
Re[8]: [почти offtop]
От: VladD2 Российская Империя www.nemerle.org
Дата: 04.02.12 22:08
Оценка: -1 :)
Здравствуйте, Alexey F, Вы писали:

AF>Для тьюринг-полноты достаточно команд brainfuck'а,


Команд может и достаточно, но у любой реализации брэйнфака конечный объем даных, а это уже нарушает условие машины тьюринга имеющей на входе потенциально бесконечный поток данных. Так что пример реализации брэйнфака никак не доказывает тюринг-полноты.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: [почти offtop]
От: Pzz Россия https://github.com/alexpevzner
Дата: 08.02.12 13:59
Оценка: +1 :)
Здравствуйте, CodingUnit, Вы писали:

CU>Я разве сказал что то об инстанционировании шаблона? Я сказал что на шаблонах нельзя написать любую программу в терминах Тьюринга, то есть нельзя писать в файлы, читать, выводить на экран, все что есть это какие то ограниченные прагма директивы конкретного компилятора, короче говоря на них нельзя написать программу любой сложности как на самом С++, C# и Nemerle потому что шаблоны не Тьюринг полны. Выкрутасы которые на них делают оперируя с определениями типов, не то на что расчитаны сами шаблоны, поэтому и компиляторы не все поддерживают эти функции, и скорее более хак чем родная функция, как и на макросах C можно сделать многое что на них никто не собирался изначально делать. Но это некачественное решение на фоне существующих систем метапрограммирования.


Ой, знатоки, ой, знатоки!

Хинт: а на машине Тьюринка можно писать в файлы, выводить на экран и управлять посудомойкой? Если нет, обладает ли машина Тьюринга тьюринговской полнотой?
Re[8]: [почти offtop]
От: Jack128  
Дата: 04.02.12 12:12
Оценка: 1 (1)
Здравствуйте, Alexey F, Вы писали:

AF>Язык может состоять из пары-тройки символов и быть абсолютно бесполезным, но быть тьюринг-полным. А может быть объёмным и навороченным языком запросов к БД и не быть тьюринг-полным (SQL (был таким, как минимум — сейчас не знаю)).


в диалектах, поддерживающих рекурсивные запросы(Oracle, MSSQL, Firebird) — тьюринг-полон
Re[3]: [почти offtop]
От: Gaperton http://gaperton.livejournal.com
Дата: 06.02.12 08:22
Оценка: 1 (1)
Здравствуйте, CodingUnit, Вы писали:

CU>>>Тьюринг полны это ты погорячился, по определению "В теории вычислимости исполнитель (множество вычисляющих элементов) называется тьюринг-полным, если на нём можно реализовать любую вычислимую функцию", можно ли на шаблонах реализовать любую? Мы пришли к выводу что нет.

AF>>Можно поподробнее выделенное? Или здесь имеется ввиду ограничение на число рекурсивно вложенных инстанциаций шаблона?

CU>Я разве сказал что то об инстанционировании шаблона? Я сказал что на шаблонах нельзя написать любую программу в терминах Тьюринга, то есть нельзя писать в файлы, читать, выводить на экран...


В "терминах Тьюринга" речь идет о возможности реализации любой вычислимой (частично-рекурсивной, согласно тезису Черча) функции.

О возможности писать в файлы — это не в терминах Тьюинга, а в терминах Васи Пупкина.
Re[26]: Тюринг-полные ли шаблоны C++?
От: m e  
Дата: 14.02.12 18:52
Оценка: 1 (1)
VD>Ошибся и не раз.

ну что же, я собираюсь повторять этот процесс до тех пор, пока ошибок не останется
Re[6]: [почти offtop]
От: CodingUnit Россия  
Дата: 04.02.12 10:53
Оценка: :)
Здравствуйте, catbert, Вы писали:

C>Тюринг говорил о вычислениях а не об IO. Опять же, если добавить примитив system, который вызывает из шаблона любую системную функцию, то шаблоны моментально станут Тюринг-полными и по вашему определению.


Так вот сначала надо добавить этот примитив чтобы возможно было выполнять любую функцию, но сейчас такой возможность нет, поэтому и не полны по тьюрингу.
Re[12]: [почти offtop]
От: Аноним  
Дата: 04.02.12 13:50
Оценка: :)
Здравствуйте, _Claus_, Вы писали:


попробуй написать на макросах факториал. У меня не вышло. В реальности это и есть тест на первоклассность
Re[14]: [почти offtop]
От: Аноним  
Дата: 04.02.12 14:06
Оценка: :)
Здравствуйте, CodingUnit, Вы писали:

CU>А что требуется? Вывести результат факториала числа? Или код факториала?


Требуется написать макрос вычисляющий факториал 5 с использованием только макросов, без использования функции. То есть сгенерированый код должен быть 120.
Re[7]: [почти offtop]
От: VladD2 Российская Империя www.nemerle.org
Дата: 05.02.12 00:28
Оценка: -1
Здравствуйте, Lloyd, Вы писали:

VD>>Машина Тюринга — это абстракция, а не что-то конекретное. Она не должна что куда-то писать и т.п. Ее вообще в природе создать нельзя, так как постулат с непрерывной лентой физически не выполним.


L>С бесконечной.


Ох любишь ты к словам прицепиться . Ну, пусть будет по-твоему.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[8]: [почти offtop]
От: Lloyd Россия  
Дата: 05.02.12 00:36
Оценка: -1
Здравствуйте, VladD2, Вы писали:

L>>С бесконечной.


VD>Ох любишь ты к словам прицепиться . Ну, пусть будет по-твоему.


Ох, любишь ты на личности переходить, даже когда нет вроде повода.
Re[9]: [почти offtop]
От: VladD2 Российская Империя www.nemerle.org
Дата: 05.02.12 14:02
Оценка: -1
Здравствуйте, Lloyd, Вы писали:

L>Минус объяснишь, или просто не с той ноги встал?


К переходу на личности мое замечание отношения не имеет, но развивать тему я не хочу. Посему оценил и забыл.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[11]: Тюринг-полные ли шаблоны C++?
От: m e  
Дата: 09.02.12 16:45
Оценка: :)
WH>Таких задач не бывает.
WH>Ты озвучил решение.
WH>Причем сферическое в вакууме.

ахринеть этот должен был говорить я, пытаясь защитить негибкий с++ от гибкого немерле, на котором легко делается все, что программист захочет

ладно, я предлагаю компромисс: я соглашаюсь на "сферическое в вакууме" и не доказываю, что оно нужно, а вы с владом рассказываете, *что* приводит к трудностям реализовать это на немерле

т.е. в немерле когда-то было принято design decision, которое сейчас мешает это сделать; оно, вероятно, было принято не с потолка, а исходя из каких-то use case-ов или соображений -- вот эти use case-ы и соображения как раз и интересны
Re[9]: Тюринг-полные ли шаблоны C++?
От: VladD2 Российская Империя www.nemerle.org
Дата: 10.02.12 14:46
Оценка: +1
Здравствуйте, FR, Вы писали:

FR>В шаблонах вполне осмысленно, конечно если тип X обобщенный.


Если он обобщенный, то проверять ты будешь не левых тип Х который по имени будешь искать, а параметр типов.
Меня интересует смысл именно этого кода. Я его не могу уловить.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[11]: [почти offtop]
От: VladD2 Российская Империя www.nemerle.org
Дата: 10.02.12 16:30
Оценка: -1
Здравствуйте, Lloyd, Вы писали:

L>К переходу на личности замечание имеет самое прямое отношение, ибо аппелирует не к предмету обсуждения, а к личности собеседника, выставляя ее (личность) в негативном свете.


Оно не апеллирует, а просто замечает, что ответ твой не по дулу. Ну, а то, что ты считаешь плохим делом докапывание к словам — это хорошо. Может в следующий раз подумаешь надо ли давать совершенно бессмысленные комментарии. Ведь и без тебя все все поняли.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[12]: [почти offtop]
От: Lloyd Россия  
Дата: 10.02.12 21:29
Оценка: :)
Здравствуйте, VladD2, Вы писали:

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


L>>К переходу на личности замечание имеет самое прямое отношение, ибо аппелирует не к предмету обсуждения, а к личности собеседника, выставляя ее (личность) в негативном свете.


VD>Оно не апеллирует, а просто замечает, что ответ твой не по дулу. Ну, а то, что ты считаешь плохим делом докапывание к словам — это хорошо. Может в следующий раз подумаешь надо ли давать совершенно бессмысленные комментарии. Ведь и без тебя все все поняли.


это ж надо сколько раз ты в одном посте соврал. Ты открываешь новые горизонты:
1. Твой ответ именно что аппелирует к личности, причем буквально, даже и "придираться" ни к чему не надо.
2. Твой ответ вообще никак не упоминает мой пост, он — исключительно о моей персоне, а не о том, что там было написано. Это особенно прискорбно наблюдать, учитывая то, что тот пост был исключительно в твою поддержку.
3. К какого докарывания к словам не было. Непрерывность и бесконечность не имеют ничего общего.
4. Бессмысленность комментария существует исключительно в глазах читающего. Если тебе была непонятна разница между непрерывностью и бесконечностью, не стоило вытаякиввть это на публику, я мог бы объяснить разницу и в частной переписке. Ты имел недавно возможность убедиться, что я не против ответить на все твои вопросы.
5. Фразу "все и без тебя" хорошобы подкреплять ссылками и объяснениями кто именно и что именно понял. А то выглядит как какая-то несуоазица.
Re[13]: [почти offtop]
От: VladD2 Российская Империя www.nemerle.org
Дата: 10.02.12 21:57
Оценка: -1
Здравствуйте, Lloyd, Вы писали:

L>это ж надо сколько раз ты в одном посте соврал. Ты открываешь новые горизонты:

L>1. Твой ответ именно что аппелирует к личности, причем буквально, даже и "придираться" ни к чему не надо.
L>2. Твой ответ вообще никак не упоминает мой пост, он — исключительно о моей персоне, а не о том, что там было написано. Это особенно прискорбно наблюдать, учитывая то, что тот пост был исключительно в твою поддержку.
L>3. К какого докарывания к словам не было. Непрерывность и бесконечность не имеют ничего общего.
L>4. Бессмысленность комментария существует исключительно в глазах читающего. Если тебе была непонятна разница между непрерывностью и бесконечностью, не стоило вытаякиввть это на публику, я мог бы объяснить разницу и в частной переписке. Ты имел недавно возможность убедиться, что я не против ответить на все твои вопросы.
L>5. Фразу "все и без тебя" хорошобы подкреплять ссылками и объяснениями кто именно и что именно понял. А то выглядит как какая-то несуоазица.

Ты маньяк .
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[14]: [почти offtop]
От: Lloyd Россия  
Дата: 11.02.12 14:06
Оценка: :)
Здравствуйте, VladD2, Вы писали:

VD>Ты маньяк .


ты закончил? Струя поноса иссякла или ждать нового прихода?
Тюринг-полные ли шаблоны C++?
От: CodingUnit Россия  
Дата: 04.02.12 10:02
Оценка:
Здравствуйте, catbert, Вы писали:

C>Тем не менее, шаблоны не "плохи". Они чудесно выполняют свою главную функцию (поддержка обобщенного программирования), да еще и Тюринг-полны. Но в реалиях .НЕТ-а, имхо, более оптимальным выбором метапрограммирования являются макросы+генерики.


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

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

05.02.12 03:18: Ветка выделена из темы чем плохи шаблоны?
Автор:
Дата: 04.02.12
— VladD2
05.02.12 03:19: Перенесено модератором из 'Nemerle' — VladD2
Re: [почти offtop]
От: Alexey F  
Дата: 04.02.12 10:14
Оценка:
Здравствуйте, CodingUnit, Вы писали:

CU>Тьюринг полны это ты погорячился, по определению "В теории вычислимости исполнитель (множество вычисляющих элементов) называется тьюринг-полным, если на нём можно реализовать любую вычислимую функцию", можно ли на шаблонах реализовать любую? Мы пришли к выводу что нет.

Можно поподробнее выделенное? Или здесь имеется ввиду ограничение на число рекурсивно вложенных инстанциаций шаблона?
Re[3]: [почти offtop]
От: Alexey F  
Дата: 04.02.12 10:32
Оценка:
Здравствуйте, CodingUnit, Вы писали:

CU>Я разве сказал что то об инстанционировании шаблона?

Я предположил этот аргумент.

CU>Я сказал что на шаблонах нельзя написать любую программу в терминах Тьюринга, то есть нельзя писать в файлы, читать, выводить на экран

Пардон? Сама машина Тьюринга может не иметь возможности читать/писать в файлы и что-либо выводить на экран.
Равно как и программа для иного микроконтроллера, из всех возможностей имеющая лишь пинать пару-тройку ножек, может быть реализацией машины Тьюринга для небесконечной ленты.
Re[4]: [почти offtop]
От: CodingUnit Россия  
Дата: 04.02.12 10:37
Оценка:
Здравствуйте, catbert, Вы писали:

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


C>Тут Тюринг ни при чем он про рисование на экране не говорил.


Он говорил о любой функции, а на современных машинах это функции операционной системы.
Re[4]: [почти offtop]
От: CodingUnit Россия  
Дата: 04.02.12 10:40
Оценка:
Здравствуйте, Alexey F, Вы писали:

CU>>Я сказал что на шаблонах нельзя написать любую программу в терминах Тьюринга, то есть нельзя писать в файлы, читать, выводить на экран

AF> Пардон? Сама машина Тьюринга может не иметь возможности читать/писать в файлы и что-либо выводить на экран.
AF>Равно как и программа для иного микроконтроллера, из всех возможностей имеющая лишь пинать пару-тройку ножек, может быть реализацией машины Тьюринга для небесконечной ленты.

Тем не менее она должна быть возможна выполнять все функции что возможны на этой машине, мы говорим о современных архитектурах а не машины 50 летней давности и тема у нас о шаблонах, так чем они Тьюринг полны по вашему?
Re[5]: [почти offtop]
От: Alexey F  
Дата: 04.02.12 10:45
Оценка:
Здравствуйте, CodingUnit, Вы писали:

CU>Он говорил о любой функции, а на современных машинах это функции операционной системы.

Когда он это говорил? Можно цитату или ссылку на источник (см. выделенное ниже)?
Мои источники и память говорят лишь о машине, оперирующей над последовательностью операций на (разбитой на ячейки) ленте, с возможностью перемещаться по этой ленте влево и вправо, считывать и перезаписывать ячейки на оной для некоторого набора команд. Как раз эта машина может реализовать любые вычислительные ф-ции, да хоть эмуляцию любой современной машины со всеми её потрохами и запуском современной же операционной системы на ней.
Re[5]: [почти offtop]
От: catbert  
Дата: 04.02.12 10:47
Оценка:
Здравствуйте, CodingUnit, Вы писали:

CU>Он говорил о любой функции, а на современных машинах это функции операционной системы.


Тюринг говорил о вычислениях а не об IO. Опять же, если добавить примитив system, который вызывает из шаблона любую системную функцию, то шаблоны моментально станут Тюринг-полными и по вашему определению.
Re[7]: [почти offtop]
От: Аноним  
Дата: 04.02.12 11:00
Оценка:
Здравствуйте, CodingUnit, Вы писали:

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


C>>Тюринг говорил о вычислениях а не об IO. Опять же, если добавить примитив system, который вызывает из шаблона любую системную функцию, то шаблоны моментально станут Тюринг-полными и по вашему определению.


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


Добавляется через прагму. Только полнота по тьюринигу не зависит от ввода вывода. Это возможность написать программу которая по входным данным выдает выходные по алгоритму конечной длинны
Re[6]: [почти offtop]
От: CodingUnit Россия  
Дата: 04.02.12 11:03
Оценка:
Здравствуйте, Alexey F, Вы писали:

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


CU>>Он говорил о любой функции, а на современных машинах это функции операционной системы.

AF>Когда он это говорил? Можно цитату или ссылку на источник (см. выделенное ниже)?
AF>Мои источники и память говорят лишь о машине, оперирующей над последовательностью операций на (разбитой на ячейки) ленте, с возможностью перемещаться по этой ленте влево и вправо, считывать и перезаписывать ячейки на оной для некоторого набора команд. Как раз эта машина может реализовать любые вычислительные ф-ции, да хоть эмуляцию любой современной машины со всеми её потрохами и запуском современной же операционной системы на ней.

Смотря что понимать под множеством выполнимых функций, если мы говорим о сравнении полноты языков программирования, то шаблоны вряд ли можно назвать полным формализмом. И ОС на нем не запустить, и команд как таковых нет.
Re[5]: [почти offtop]
От: Alexey F  
Дата: 04.02.12 11:07
Оценка:
Здравствуйте, CodingUnit, Вы писали:

CU>Тем не менее она должна быть возможна выполнять все функции что возможны на этой машине

Нет, она не должна. Серьёзно, Алан Тьюринг и словом об этом не обмолвился.

CU> мы говорим о современных архитектурах а не машины 50 летней давности и тема у нас о шаблонах, так чем они Тьюринг полны по вашему?

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

Даже brainfuck(<>[]+-.,) тьюринг-полон — и это не мои домыслы. Я даже не знаю, стоит ли приводить источники, где упоминается о его тьюриг-полноте...
Re[8]: [почти offtop]
От: CodingUnit Россия  
Дата: 04.02.12 11:07
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Добавляется через прагму.


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

A> Только полнота по тьюринигу не зависит от ввода вывода. Это возможность написать программу которая по входным данным выдает выходные по алгоритму конечной длинны


Так как можно по входным данным в шаблонах написать программу которая выдает выходные?
Re[7]: [почти offtop]
От: Аноним  
Дата: 04.02.12 11:08
Оценка:
Здравствуйте, CodingUnit, Вы писали:

CU>Смотря что понимать под множеством выполнимых функций, если мы говорим о сравнении полноты языков программирования, то шаблоны вряд ли можно назвать полным формализмом. И ОС на нем не запустить, и команд как таковых нет.

Запуск ос не возможно только по одной причине. Ограничение глубины рекурсии. Да и не совсем понятно как смотреть ее исполнение.
Re[7]: [почти offtop]
От: Alexey F  
Дата: 04.02.12 11:20
Оценка:
Здравствуйте, CodingUnit, Вы писали:

CU>Смотря что понимать под множеством выполнимых функций, если мы говорим о сравнении полноты языков программирования, то шаблоны вряд ли можно назвать полным формализмом. И ОС на нем не запустить, и команд как таковых нет.

Для тьюринг-полноты достаточно команд brainfuck'а, а реализация brainfuck на шаблонах C++ имеется Ввод/вывод, конечно, неинтерактивный, иногда в реализациях для простоты убирают ввод.
Вот минимум одна из них (C++11):
http://devmaster.net/forums/topic/13973-c-template-metaprogramming-brainfck-interpreter/

CU>о сравнении полноты языков программирования

Ну так абстрактная "полнота" и "тьюринг-полнота" это совершенно разные вещи
Язык может состоять из пары-тройки символов и быть абсолютно бесполезным, но быть тьюринг-полным. А может быть объёмным и навороченным языком запросов к БД и не быть тьюринг-полным (SQL (был таким, как минимум — сейчас не знаю)).

На самом деле, если дать шаблонам C++ бесконечную память (см. машину Тьюринга) и (сверх)высокую производительность, на них можно построить виртуальную машину, где будет работать ОС, "читать"-"писать" свои виртуальные файлы, общаться с виртуальной клавиатурой и т.п. Это утверждение применимо и для brainfuck'а.

CU>и команд как таковых нет.

Да есть они.
Re[8]: [почти offtop]
От: CodingUnit Россия  
Дата: 04.02.12 11:53
Оценка:
Здравствуйте, Alexey F, Вы писали:

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


CU>>Смотря что понимать под множеством выполнимых функций, если мы говорим о сравнении полноты языков программирования, то шаблоны вряд ли можно назвать полным формализмом. И ОС на нем не запустить, и команд как таковых нет.

AF>Для тьюринг-полноты достаточно команд brainfuck'а, а реализация brainfuck на шаблонах C++ имеется Ввод/вывод, конечно, неинтерактивный, иногда в реализациях для простоты убирают ввод.
AF>Вот минимум одна из них (C++11):
AF>http://devmaster.net/forums/topic/13973-c-template-metaprogramming-brainfck-interpreter/

AF>На самом деле, если дать шаблонам C++ бесконечную память (см. машину Тьюринга) и (сверх)высокую производительность, на них можно построить виртуальную машину, где будет работать ОС, "читать"-"писать" свои виртуальные файлы, общаться с виртуальной клавиатурой и т.п. Это утверждение применимо и для brainfuck'а.


Это уже все же мечты, реально же вряд ли кто то будет строить и запускать такие виртуальные машины. Как расширение системы типов С++ шаблоны годятся, и в свое время пригодились, на некоторых платформах лучше ничего и не найти, но когда возможны более удобные системы метапрограммирования, намеренно их использовать это уже не лучшее решение.
Re[9]: [почти offtop]
От: Alexey F  
Дата: 04.02.12 12:06
Оценка:
Здравствуйте, CodingUnit, Вы писали:

CU>Это уже все же мечты, реально же вряд ли кто то будет строить и запускать такие виртуальные машины.

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

CU>Как расширение системы типов С++ шаблоны годятся, и в свое время пригодились, на некоторых платформах лучше ничего и не найти, но когда возможны более удобные системы метапрограммирования, намеренно их использовать это уже не лучшее решение.

+1 Если бы в C++ или хотя бы для native было доступно лучшее решение в своё время, шаблоны никто даже не додумался бы копать.
Re[7]: [почти offtop]
От: _Claus_  
Дата: 04.02.12 12:10
Оценка:
CU>Смотря что понимать под множеством выполнимых функций, если мы говорим о сравнении полноты языков программирования, то шаблоны вряд ли можно назвать полным формализмом. И ОС на нем не запустить, и команд как таковых нет.

Я никак не пойму, почему надо проводить резкую границу, если можно все рассматривать в рамках одного формализма,

макроса, который принимает и типы в качестве аргументов. что тут военного?

мне только не хватает возможности, чтобы такой макрос мог читать определение как traits.

вот здесь написано
Автор: mkizub
Дата: 10.12.08
, что это задача на пять минут.
Re[8]: [почти offtop]
От: CodingUnit Россия  
Дата: 04.02.12 13:14
Оценка:
Здравствуйте, _Claus_, Вы писали:


CU>>Смотря что понимать под множеством выполнимых функций, если мы говорим о сравнении полноты языков программирования, то шаблоны вряд ли можно назвать полным формализмом. И ОС на нем не запустить, и команд как таковых нет.


_C_>Я никак не пойму, почему надо проводить резкую границу, если можно все рассматривать в рамках одного формализма,


_C_>макроса, который принимает и типы в качестве аргументов. что тут военного?


_C_>мне только не хватает возможности, чтобы такой макрос мог читать определение как traits.


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

_C_>вот здесь написано
Автор: mkizub
Дата: 10.12.08
, что это задача на пять минут.


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


[template(T)]
class Test
{
  DB(T) db;
}

Use() : void
{
  def abc = instance(Test, int); // тут можно придумать синтаксис для инстанционирования, я показал простейший
}


Соответсвенно макросы template и instance должны понимать друг друга, добавлять куда то инфмормацию во время компиляции чтобы генерировать классы, но этот случай вполне возможен
Re[9]: [почти offtop]
От: Аноним  
Дата: 04.02.12 13:20
Оценка:
на сколько я понимаю не возможно на макросах сделать шаблоны так как макросы не первоклассные сущности. Это Ограничение макросов.
Re[10]: [почти offtop]
От: CodingUnit Россия  
Дата: 04.02.12 13:38
Оценка:
Здравствуйте, Аноним, Вы писали:

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


Как мне кажется можно, просто обработку надо производить внутри макроса, чтобы он умел обрабатывать выражения рекурсивно, например:


[template(T)]
class Test
{
}

Test @ <Test @ <int> >




@ <> позволяет инстанционировать шаблон макроса, не знаю сработает ли этот синтаксис не проверял, но синтаксис можно придумать, суть не меняется. При вызове макроса @<> или instance будет производится обработка внутренних выражений входящих в состав входных аргументов то есть Test @ <int>, макросы позволяют вызывать макросы и самих себя, только подаются они не как первоклассные сущности а как выражения, по которым можно определить содержимое параметров. А в промежуточных структурах можно хранить любой код, хоть новый компилятор можно сделать в макросе, такие есть например Nemerle.Statechart библиотека автоматов на dsl синтаксисе, Nemerle.Peg генерирующий парсеры, все это макросы. Между шаблонами и макросами много общего просто макросы несколько по другому обрабатываются, и в них больше свободы. Все это можно сделать, просто немного времени нужно и пока задач таких не было.
Re[9]: [почти offtop]
От: _Claus_  
Дата: 04.02.12 13:39
Оценка:
Здравствуйте, CodingUnit, Вы писали:

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



CU>>>Смотря что понимать под множеством выполнимых функций, если мы говорим о сравнении полноты языков программирования, то шаблоны вряд ли можно назвать полным формализмом. И ОС на нем не запустить, и команд как таковых нет.


_C_>>Я никак не пойму, почему надо проводить резкую границу, если можно все рассматривать в рамках одного формализма,


_C_>>макроса, который принимает и типы в качестве аргументов. что тут военного?


_C_>>мне только не хватает возможности, чтобы такой макрос мог читать определение как traits.


CU>Да это мы по поводу тьюринг полноты говорили, оно не относится к проблеме использования генерик параметров в макросах


_C_>>вот здесь написано
Автор: mkizub
Дата: 10.12.08
, что это задача на пять минут.


CU>Не знаю, если заняться можно и вариант шаблонов на макросах сделать, чтобы тип связывался не в рантайме, или тебе можно переписать задачу так чтобы тип связывался не как генерик, а как макрос изначально то есть подавался в виде выражения в остальные макроса типа:


CU>

CU>[template(T)]
CU>class Test
CU>{
CU>  DB(T) db;
CU>}

CU>Use() : void
CU>{
CU>  def abc = instance(Test, int); // тут можно придумать синтаксис для инстанционирования, я показал простейший
CU>}
CU>


CU>Соответсвенно макросы template и instance должны понимать друг друга, добавлять куда то инфмормацию во время компиляции чтобы генерировать классы, но этот случай вполне возможен


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

или такой вариант:

macros X[T,Y] ...
Re[10]: [почти offtop]
От: CodingUnit Россия  
Дата: 04.02.12 13:40
Оценка:
Здравствуйте, Аноним, Вы писали:

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


На этапе компиляции все же можно назвать макросы первоклассными сущностями на равне с шаблонами, потому что они могут передаваться также в макросы, обрабатываться и раскрываться, но больше никуда, в функцию их не передать, на этапе выполнения, только в этом контексте они не первоклассные сущности, как вообщем и шаблоны.
Re[11]: [почти offtop]
От: _Claus_  
Дата: 04.02.12 13:45
Оценка:
CU>На этапе компиляции все же можно назвать макросы первоклассными сущностями на равне с шаблонами, потому что они могут передаваться также в макросы, обрабатываться и раскрываться, но больше никуда, в функцию их не передать, на этапе выполнения, только в этом контексте они не первоклассные сущности, как вообщем и шаблоны.

Мысленно вместе!
Re[13]: [почти offtop]
От: CodingUnit Россия  
Дата: 04.02.12 13:59
Оценка:
Здравствуйте, Аноним, Вы писали:

А>попробуй написать на макросах факториал. У меня не вышло. В реальности это и есть тест на первоклассность


А что требуется? Вывести результат факториала числа? Или код факториала?
Re[9]: [почти offtop]
От: _Claus_  
Дата: 04.02.12 14:09
Оценка:
CU>

CU>[template(T)]
CU>class Test
CU>{
CU>  DB(T) db;
CU>}

CU>Use() : void
CU>{
CU>  def abc = instance(Test, int); // тут можно придумать синтаксис для инстанционирования, я показал простейший
CU>}
CU>


CU>Соответсвенно макросы template и instance должны понимать друг друга, добавлять куда то инфмормацию во время компиляции чтобы генерировать классы, но этот случай вполне возможен


я бы предложил такой вариант синтаксиса, который впрочем уже описывал, как более легкий.

macros Mx[X]
../здесь допускается описание как

описание в коде, на которое он реагирует


Mx[T]
   i : T
   Z(o : int) :  T
     ...
 ...



т.е. макрос возвращает вычисляемый тип и по сути им является.

и где-то в коде

meth() : Mx[int]

и все в шоколаде.

почему не ставить в описании class, да потому что вернуть может и struct и int, ...

что скажешь?
Re[10]: [почти offtop]
От: _Claus_  
Дата: 04.02.12 14:10
Оценка:
../здесь допускается описание как

читать как

../здесь допускается описание как у класса
Re[15]: [почти offtop]
От: CodingUnit Россия  
Дата: 04.02.12 14:31
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Требуется написать макрос вычисляющий факториал 5 с использованием только макросов, без использования функции. То есть сгенерированый код должен быть 120.


Пожалуйста типичный пример использования макросов:



// в отдельной макро сборке
macro factorial(n : int)
{
  if (n == 0) <[ 1 ]> else <[ $n * factorial($(n - 1)) ]>
}

// консольный пример
using System;
using System.Console;

module Test
{
  Main() : void
  {
    WriteLine(factorial(5)); // 120
  }

}
Re[10]: [почти offtop]
От: CodingUnit Россия  
Дата: 04.02.12 15:03
Оценка:
CU>>Соответсвенно макросы template и instance должны понимать друг друга, добавлять куда то инфмормацию во время компиляции чтобы генерировать классы, но этот случай вполне возможен

_C_>я бы предложил такой вариант синтаксиса, который впрочем уже описывал, как более легкий.


_C_>macros Mx[X]

_C_> ../здесь допускается описание как

_C_>что скажешь?


сейчас расширить синтаксис объявления макросов не просто, проще сделать особый синтаксис для самих макросов template и instance. Сейчас главное опробовать идею, это можно сделать пока на любом синтаксисе, если пойдет уже тогда придумать для таких макросов что то свое. Кто займется реализацией самих макросов template и instance вот в чем вопрос.
Re[11]: [почти offtop]
От: _Claus_  
Дата: 04.02.12 20:39
Оценка:
CU>сейчас расширить синтаксис объявления макросов не просто, проще сделать особый синтаксис для самих макросов template и instance.

ключевое слово macrotype может для такого подойти. template это все-таки вполне определенное понятие.
а параметры макротипа могут (в теории) не только типы, но и числа — размерность например. возможно и строки — чего-то куда подставить.
последнее опционально, но заложить возможность было бы хорошо. а если макротип возвращает тип, то потребности в instance не будет.

CU>Сейчас главное опробовать идею, это можно сделать пока на любом синтаксисе, если пойдет уже тогда придумать для таких макросов что то свое. Кто займется реализацией самих макросов template и instance вот в чем вопрос.


кроме тебя, на данном этапе, скорее всего никто. ты самый сочувствующий.. из тех кто пилит компилятор.
Re: Тюринг-полные ли шаблоны C++?
От: VladD2 Российская Империя www.nemerle.org
Дата: 04.02.12 22:03
Оценка:
Здравствуйте, CodingUnit, Вы писали:

CU>Тьюринг полны это ты погорячился, по определению "В теории вычислимости исполнитель (множество вычисляющих элементов) называется тьюринг-полным, если на нём можно реализовать любую вычислимую функцию", можно ли на шаблонах реализовать любую? Мы пришли к выводу что нет.


Можно. Только тюринг-полнтота еще не все. Еще гужны модули, библиотеки, общение с внешним миром, возможность анализировать код. Вот с этим у них полная задница. Да и генерировать код ими крайне неудобно и не эффективно.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[10]: [почти offtop]
От: VladD2 Российская Империя www.nemerle.org
Дата: 04.02.12 22:18
Оценка:
Здравствуйте, Аноним, Вы писали:

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


А какова связь между первокласностью сущности и возможности производить вычисления? Вот в С циклы и условные операторы первоклассные сущности? Нет? А это им мешает реализовать ту же машину тьюринга?

Плюс зачем, скажите мне на милость, в языке с макросами реализовывать рекурсивное воплощение? Чтобы производить на них вычисления? Но это же идиотизм! У нас уже есть вычисления любой сложности и гибкости. И в них, в том числе можно использовать весь язык, включая функции как первоклассные сущности .

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

Но все это никак не влиять не необходимость поддержки рекурсивного раскрытия.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[11]: [почти offtop]
От: VladD2 Российская Империя www.nemerle.org
Дата: 04.02.12 22:21
Оценка:
Здравствуйте, CodingUnit, Вы писали:

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


Да все эти разглагольствования о первоклассности от не понимания предмета разговора. Макрос в Н — это точка входа в грамматике. А его реализация вполне себе может находиться в функции которая очень даже первоклассная.

Макрос может прочесть синтаксическое определение и произвести любую трасформацию. В том числе и эмулировать рекурсивное раскрытие шаблонов. Это ни разу не проблема.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[13]: [почти offtop]
От: VladD2 Российская Империя www.nemerle.org
Дата: 04.02.12 22:29
Оценка:
Здравствуйте, Аноним, Вы писали:

А>попробуй написать на макросах факториал. У меня не вышло. В реальности это и есть тест на первоклассность


Это говорит исключительно о твоих знаниях. Надо было просто зайти сюда и спросить.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[15]: [почти offtop]
От: VladD2 Российская Империя www.nemerle.org
Дата: 04.02.12 22:33
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Требуется написать макрос вычисляющий факториал 5 с использованием только макросов, без использования функции. То есть сгенерированый код должен быть 120.


А зачем же без функции? Любишь циклы?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: [почти offtop]
От: VladD2 Российская Империя www.nemerle.org
Дата: 04.02.12 22:40
Оценка:
Здравствуйте, CodingUnit, Вы писали:

CU>Тем не менее она должна быть возможна выполнять все функции что возможны на этой машине, мы говорим о современных архитектурах а не машины 50 летней давности и тема у нас о шаблонах, так чем они Тьюринг полны по вашему?


Блин. Ты тут уже весь форум заполонил этим мракобесем. Машина Тюринга — это абстракция, а не что-то конекретное. Она не должна что куда-то писать и т.п. Ее вообще в природе создать нельзя, так как постулат с непрерывной лентой физически не выполним. Прочит о том о чем ведешь речь.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: [почти offtop]
От: Lloyd Россия  
Дата: 04.02.12 23:23
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Машина Тюринга — это абстракция, а не что-то конекретное. Она не должна что куда-то писать и т.п. Ее вообще в природе создать нельзя, так как постулат с непрерывной лентой физически не выполним.


С бесконечной.
Re[8]: [почти offtop]
От: Lloyd Россия  
Дата: 05.02.12 13:12
Оценка:
Здравствуйте, VladD2, Вы писали:

L>>С бесконечной.


VD>Ох любишь ты к словам прицепиться . Ну, пусть будет по-твоему.


Минус объяснишь, или просто не с той ноги встал?
Re: Доказательство полноты.
От: CodingUnit Россия  
Дата: 06.02.12 14:54
Оценка:
Здравствуйте, WolfHound, Вы писали:

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


Спасибо Вам за труд, только я уже давно понял суть вопроса, мне доказывать это не надо.
Re[2]: Тюринг-полные ли шаблоны C++?
От: m e  
Дата: 08.02.12 12:02
Оценка:
VD>Можно. Только тюринг-полнтота еще не все.

тут да, для полного счастья одной тьюринг-полноты мало -- надо еще суметь прочесть входные данные из AST и потом суметь выплюнуть результать работы обратно в AST

кое-где это в с++ похоже невозможно, кое-где делается через SFINAE

а как обстоят щас дела в немерле?

скажем, мне надо создать какой-то код в том случае, если в классе Х имеется поле у, а иначе ничего не делать
Re[3]: Тюринг-полные ли шаблоны C++?
От: WolfHound  
Дата: 08.02.12 12:17
Оценка:
Здравствуйте, m e, Вы писали:

ME>а как обстоят щас дела в немерле?

Отлично.

ME>скажем, мне надо создать какой-то код в том случае, если в классе Х имеется поле у, а иначе ничего не делать

Нивапрос.
when (typeBuilder.GetMembers().Exists(_ => { | IField as field => field.Name == "y" | _ => false } ))
{
    ...
}
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[4]: Тюринг-полные ли шаблоны C++?
От: m e  
Дата: 08.02.12 12:19
Оценка:
WH>
WH>when (typeBuilder.GetMembers().Exists(_ => { | IField as field => field.Name == "y" | _ => false } ))
WH>{
WH>    ...
WH>}
WH>


а где тут "Х" ?

и раз не вопрос -- вместо "..." скажем добавить поле z целого типа в класс T
Re[5]: Тюринг-полные ли шаблоны C++?
От: WolfHound  
Дата: 08.02.12 12:37
Оценка:
Здравствуйте, m e, Вы писали:

ME>а где тут "Х" ?

В typeBuilder лежит.
Есть много способов это сделать.
И на практике искать тип по имени как правило не нужно. Более того это вредно.

ME>и раз не вопрос -- вместо "..." скажем добавить поле z целого типа в класс T

typeBuilder.Define(<[decl: z : int]>);
И оно даже в интелесенсе будет доступно.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[6]: Тюринг-полные ли шаблоны C++?
От: m e  
Дата: 08.02.12 12:41
Оценка:
ME>>а где тут "Х" ?
WH>В typeBuilder лежит.
WH>Есть много способов это сделать.
WH>И на практике искать тип по имени как правило не нужно. Более того это вредно.

для начала все же по имени -- как в с++

а потом -- как надо искать и почему вредно
Re[7]: Тюринг-полные ли шаблоны C++?
От: WolfHound  
Дата: 08.02.12 13:11
Оценка:
Здравствуйте, m e, Вы писали:

ME>для начала все же по имени -- как в с++

С этим мороки много.
Но это нужно, только если ты делаешь что-то совсем навороченное.
Обычно же тебе и так известен TypeBuilder того типа над которым ты хочешь поиздеваться.

ME>а потом -- как надо искать и почему вредно

А по тому, что возникает куча вопросов с тем, где искать этот тип.
Ибо типов с одним именем может быть много.
Может ли тип быть в другой сборке.
...
И решать эти вопросы нужно каждый раз по месту.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[4]: Тюринг-полные ли шаблоны C++?
От: VladD2 Российская Империя www.nemerle.org
Дата: 08.02.12 13:45
Оценка:
Здравствуйте, WolfHound, Вы писали:

ME>>скажем, мне надо создать какой-то код в том случае, если в классе Х имеется поле у, а иначе ничего не делать

WH>Нивапрос.
WH>
WH>when (typeBuilder.GetMembers().Exists(_ => { | IField as field => field.Name == "y" | _ => false } ))
WH>{
WH>    ...
WH>}
WH>


С новым фильтр можно сократить до:
typeBuilder.GetMembers().Exists(x => x is IField(Name="y"))

или даже до:
typeBuilder.GetMembers().Exists(_ is IField(Name="y"))
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: Тюринг-полные ли шаблоны C++?
От: VladD2 Российская Империя www.nemerle.org
Дата: 08.02.12 13:49
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>
WH>when (typeBuilder.GetMembers().Exists(_ => { | IField as field => field.Name == "y" | _ => false } ))
WH>


А конкретно для полей проще вообще так:
when (typeBuilder.GetFields().Exists(field => field.Name == "y"))
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Тюринг-полные ли шаблоны C++?
От: VladD2 Российская Империя www.nemerle.org
Дата: 08.02.12 14:08
Оценка:
Здравствуйте, m e, Вы писали:

ME>а как обстоят щас дела в немерле?


Как и в самом начале. Без проблем. Макросы немерла имеют полный доступ к AST компилируемой программы и имеют возможность получать информацию о типах. Так же они могут добавлять классы, члены и другие элементы. Ну, и конечно же менять код внутри членов.

ME>скажем, мне надо создать какой-то код в том случае, если в классе Х имеется поле у, а иначе ничего не делать


Сделать это несомненно можно, но вопрос поставлен слишком общо. Не ясно где надо создать код. Откуда этот код узнает о классе Х. В общем, не ясен алгоритм. А без него конкретное решение не описать.

В Немерле, например, есть макрос Record. Это макро-атрибут генерирующий конструктор позволяющий проинициализировать все поля типа (за исключением специально помеченных). Его применение выглядит так:
[Record]
class A
{
  public Field : int;
  public Property : string;
}

def a1 = A(1, "test");
// использование именованных параметров, чтобы продемонстрировать имена парамтеров
def a1 = A(property="test", field = 1);

Как видно макрос создает конструктор в котором добавляет по параметру на каждое поле. В коде констурктора параметры копируются в соответствующие поля и свойства.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[8]: Тюринг-полные ли шаблоны C++?
От: VladD2 Российская Империя www.nemerle.org
Дата: 08.02.12 14:15
Оценка:
Здравствуйте, WolfHound, Вы писали:

ME>>для начала все же по имени -- как в с++

WH>С этим мороки много.

Какой мороки? Получить тип по имени ничего не стоит.
def typeBilderForX = typer.BindFixedType("X");


WH>Но это нужно, только если ты делаешь что-то совсем навороченное.


Это обычно нужно когда знаешь точное имя и нужна какая-то информация о типах.

WH>Обычно же тебе и так известен TypeBuilder того типа над которым ты хочешь поиздеваться.


Задачи бывает разные. Товарищ не потрудился озвучить ту, решаение которой хочет услышать. Вот пусть и опишет задачу по четче. А то "как в С++" — это ведь смешно звучит. В С++ всегда через задница. Зачем же так сурово?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[9]: Тюринг-полные ли шаблоны C++?
От: WolfHound  
Дата: 08.02.12 17:09
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Какой мороки? Получить тип по имени ничего не стоит.

VD>
VD>def typeBilderForX = typer.BindFixedType("X");
VD>

А теперь напиши оставшейся код, который нужен, чтобы узнать есть ли у этого типа поле "y"...
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[10]: Тюринг-полные ли шаблоны C++?
От: VladD2 Российская Империя www.nemerle.org
Дата: 09.02.12 01:17
Оценка:
Здравствуйте, WolfHound, Вы писали:

VD>>Какой мороки? Получить тип по имени ничего не стоит.

VD>>
VD>>def typeBilderForX = typer.BindFixedType("X");
VD>>

WH>А теперь напиши оставшейся код, который нужен, чтобы узнать есть ли у этого типа поле "y"...

Ты его и сам почти написал:
when (typeBilderForX.GetFields().Exists(field => field.Name == "y"))
  ...
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[11]: Тюринг-полные ли шаблоны C++?
От: WolfHound  
Дата: 09.02.12 07:37
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Ты его и сам почти написал:

Ох.
Напомню, что BindFixedType имеет тип PExpr -> FixedType.
И у FixedType нет метода GetFields.
Перегрузки, которая принимают строку у BindFixedType тоже нет.
С типами из текущей сборки (TypeBuilder) и теми которые лежат во внешних сборках (LibraryReference.ExternalTypeInfo) нужно обращаться по-разному.
Короче мороки много.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[3]: Тюринг-полные ли шаблоны C++?
От: FR  
Дата: 09.02.12 09:04
Оценка:
Здравствуйте, m e, Вы писали:

ME>скажем, мне надо создать какой-то код в том случае, если в классе Х имеется поле у, а иначе ничего не делать


На D кстати такое очень просто делается:

import std.stdio;
import std.traits;


class X
{
    public int y;
}    


class Z
{
    public int y;
}    


bool Test(T)(T t)
{
static if(__traits(compiles, X) && __traits(isSame, X, T) && hasMember!(T, "y"))
    return true;

return false;
}


void main()
{
writeln(Test(1));
writeln(Test(new X));
writeln(Test(new Z));
}
Re[4]: Тюринг-полные ли шаблоны C++?
От: m e  
Дата: 09.02.12 09:55
Оценка:
FR>static if(__traits(compiles, X) && __traits(isSame, X, T) && hasMember!(T, "y"))
FR> return true;

в D этот момент емнип подчистили, но мы пока что будем сравнивать немерле с древним с++11

кстати -- return true; не показательно; лучше сделать как я сказал -- если (__traits(compiles, X) && __traits(isSame, X, T) && hasMember!(T, "y")) то тогда добавить в класс Z поле t, иначе ничего не делать
Re[9]: Тюринг-полные ли шаблоны C++?
От: m e  
Дата: 09.02.12 10:05
Оценка:
VD>Задачи бывает разные. Товарищ не потрудился озвучить ту, решаение которой хочет услышать. Вот пусть и опишет задачу по четче.

уже озвучил

>> мне надо создать какой-то код в том случае, если в классе Х имеется поле у, а иначе ничего не делать

>> добавить поле z целого типа в класс T

могу одним предложением:

если в классе Х имеется поле у, то добавить поле z целого типа в класс T, а иначе ничего не делать (т.е. класс Т не менять)

в какой сборке там лежит этот класс Х меня волновать не должно... в пределах разумного конечно (т.е. если оно таки должно волновать по уважительной причине -- я слушаю)

VD> А то "как в С++" — это ведь смешно звучит.


нет, не смешно -- в конкурирующем языке должно быть сделано по крайней мере не хуже

VD> В С++ всегда через задница.


это я и без тебя знаю -- меня интересует, через задницу ли в немерле или там по-человечески сделано
Re[4]: Тюринг-полные ли шаблоны C++?
От: m e  
Дата: 09.02.12 10:06
Оценка:
FIX: добавить поле z целого типа в класс T

(для совместимости с прошлым постом)
Re[4]: Тюринг-полные ли шаблоны C++?
От: m e  
Дата: 09.02.12 10:20
Оценка:
VD> В общем, не ясен алгоритм. А без него конкретное решение не описать.

я *специально* не задаю слишком жесткую спецификацию, чтобы не заставить тебя повторять ненужные детали реализации этой штуки в с++

делай как это будет естественно в немерле; если твоя реализация слишком разойдется с тем, как я понимаю задачу -- будем выяснять это отдельно
Re[5]: Тюринг-полные ли шаблоны C++?
От: FR  
Дата: 09.02.12 10:32
Оценка:
Здравствуйте, m e, Вы писали:

ME>FIX: добавить поле z целого типа в класс T


ME>(для совместимости с прошлым постом)


Добавить в класс поле в D не получится язык все-таки не динамический, но сгенерировать новый класс с нужным полем
и скажем наследника старого, а иначе пустой класс без проблем:


import std.stdio;
import std.traits;


class X
{
    public int y;
}    


template Test(T) 
{
static if(__traits(compiles, X) && __traits(isSame, X, T) && hasMember!(T, "y")){
    class Test : public X {int z;}
    }
else{
    class Test {}
    }
}


void main()
{
writeln([ __traits(allMembers, Test!(int)) ]);
writeln([ __traits(allMembers, Test!(X)) ]);
}
Re[6]: Тюринг-полные ли шаблоны C++?
От: m e  
Дата: 09.02.12 11:41
Оценка:
FR>Добавить в класс поле в D не получится язык все-таки не динамический,

ну дык само собой, я даже не предполагал что кто-то попытается в рантайме поле добавлять
FR>template Test(T) 
FR>{
FR>static if(__traits(compiles, X) && __traits(isSame, X, T) && hasMember!(T, "y")){
FR>    class Test : public X {int z;}
FR>    }
FR>else{
FR>    class Test {}
FR>    }
FR>}


ммм... а так можно?

class T {
  int a;
  int b;
  int c;
  static if( hasMember!(Х, "y") ) {
    int z;
  }
}
Re[10]: Тюринг-полные ли шаблоны C++?
От: WolfHound  
Дата: 09.02.12 11:50
Оценка:
Здравствуйте, m e, Вы писали:

ME>если в классе Х имеется поле у, то добавить поле z целого типа в класс T, а иначе ничего не делать (т.е. класс Т не менять)

Таких задач не бывает.
Ты озвучил решение.
Причем сферическое в вакууме.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[7]: Тюринг-полные ли шаблоны C++?
От: FR  
Дата: 09.02.12 14:28
Оценка:
Здравствуйте, m e, Вы писали:

ME>ммм... а так можно?


Так напрямую нет, но можно с помощью миксинов:

class T {
  int a;
  int b;
  int c;
  static if( hasMember!(X, "y") ) {
    mixin("int z;");
  }
}
Re[12]: Тюринг-полные ли шаблоны C++?
От: WolfHound  
Дата: 09.02.12 17:26
Оценка:
Здравствуйте, m e, Вы писали:

ME>ахринеть этот должен был говорить я, пытаясь защитить негибкий с++ от гибкого немерле, на котором легко делается все, что программист захочет

С++ вообще не может ничего сгенерировать в другом классе.
Сколько бы ты текста не написал.

ME>ладно, я предлагаю компромисс: я соглашаюсь на "сферическое в вакууме" и не доказываю, что оно нужно, а вы с владом рассказываете, *что* приводит к трудностям реализовать это на немерле

Реализовать можно. Но будет много букв.

ME>т.е. в немерле когда-то было принято design decision, которое сейчас мешает это сделать; оно, вероятно, было принято не с потолка, а исходя из каких-то use case-ов или соображений -- вот эти use case-ы и соображения как раз и интересны

Это решение называется язык деланый студентами. Они хоть ребята толковые и талантливые, но студенты с нулевым опытом промышленной разработки. И API компилятора местами феерично.
Ты что думаешь Н2 просто так делается?
Тем не менее, сделать можно практически что угодно. Причем обычно очень сильно проще, чем на конкурирующих технологиях.
В данном случае я тебе уже раз 10 сказал, что в реальных задачах то что ты хочешь просто не встречается.
Тебе и так известен TypeBuilder того класса над которым надо поиздеваться.
Он тебе просто передаётся в макрос, который ты на класс вешаешь.
Если ты делаешь глобальный макрос, то опять же ты будешь сканировать дерево типов проекта и получишь нужные TypeBuilder'ы.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[13]: Тюринг-полные ли шаблоны C++?
От: m e  
Дата: 09.02.12 19:03
Оценка:
WH>С++ вообще не может ничего сгенерировать в другом классе.
WH>Сколько бы ты текста не написал.

это кстати хорошая мысль -- подумать, что с++ может сгенерировать, а что не может
насчет "ничего" ты сильно загнул
понятно, что в том классе, куда че-то добавляется, придется явно указать
class MyClass;
class MyClass: public GiveSomeThingTo<MyClass> {....};


при этом d-шный вариант выглядит приличнее, за исключением строки в миксине

WH>В данном случае я тебе уже раз 10 сказал, что в реальных задачах то что ты хочешь просто не встречается.


а что встречается? постройка с нуля и до конца? в случае классов -- это и в плюсах можно без макросов

добавление, по-моему, должно быть основной способ макрописания
Re[14]: Тюринг-полные ли шаблоны C++?
От: WolfHound  
Дата: 09.02.12 19:37
Оценка:
Здравствуйте, m e, Вы писали:

ME>это кстати хорошая мысль -- подумать, что с++ может сгенерировать, а что не может

ME>насчет "ничего" ты сильно загнул
Никуда я не загнул.
Ты попробуй найти класс по имени и туда что-то добавить.
Не можешь?

ME>понятно, что в том классе, куда че-то добавляется, придется явно указать

хъ
ME>при этом d-шный вариант выглядит приличнее, за исключением строки в миксине
Собственно вешание макро-атрибутов на класс это самый распространенный способ использования макросов которые что-то добавляют в типы.
  [Record, StructuralEquality, StructuralHashCode]
  public struct NToken
  {
    public StartPos : int { get; }
    public EndPos   : int { get; }

    public IsEmpty : bool { get { StartPos == EndPos } }

    public override ToString() : string
    {
      $<#"Start: $StartPos Len: $(EndPos - StartPos)"#>;
    }
  }

Макросы Record, StructuralEquality, StructuralHashCode сразу получают TypeBuilder NToken'а.
После чего достают из него поля.
И генерируют на их основе нужные методы.

ME>а что встречается?

Повторю еще раз. Искать классы по имени не нужно.
Тебе и так дадут нужный TypeBuilder.

ME>постройка с нуля и до конца? в случае классов -- это и в плюсах можно без макросов

Ну попробуй на плюсах повторить вот это: https://github.com/rampelstinskin/ParserGenerator

ME>добавление, по-моему, должно быть основной способ макрописания

Так и есть. Только для этого классы по имени искать не нужно.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[15]: Тюринг-полные ли шаблоны C++?
От: m e  
Дата: 09.02.12 20:14
Оценка:
WH>Ты попробуй найти класс по имени и туда что-то добавить.
WH>Не можешь?

навскидку не помню, можно ли перегрузить оператор -> снаружи класса

> Макросы Record, StructuralEquality, StructuralHashCode сразу получают TypeBuilder NToken'а. После чего достают из него поля. И генерируют на их основе нужные методы.


1. тут идет дописывание, а не постройка с 0

2. про это я уже писал -- шаблоны, несмотря на тьюринг-полноту, просто не могут получить нужные данные

WH>Ну попробуй на плюсах повторить вот это: https://github.com/rampelstinskin/ParserGenerator


"это" это https://github.com/rampelstinskin/ParserGenerator/blob/master/Test/Main.n ?

ты давай опять словами, а то идея по коду не полностью восстанавливается

то, что я восстановил -- с точностью до тормозов лишнего виртуального вызова функции -- без проблем

без тормозов -- надо подумать, но сейчас лень

с чуть худшим синтаксисом -- перетащив его в треугольные скобки -- без тормозов
Re[15]: Тюринг-полные ли шаблоны C++?
От: m e  
Дата: 09.02.12 21:41
Оценка:
WH>Ты попробуй найти класс по имени и туда что-то добавить.

все это мне было очень интересно обдумать для с++, правда не понятно зачем (см. ниже)
кое-что там можно сделать, но интересней что нельзя без своего препроцессора
нельзя похоже сделать так, чтобы добавленное в класс в файле Ф1 поле было видно и из файла Ф2 (ну еще там сложности с итерацией по полям, но на это можно плюнуть)

более фундаментальная и полезная вещь -- это добавление в "рядом лежащий" класс, примерно как у тебя в примере StructuralEquality; но при этом надо уметь *читать* другие классы просто по имени

читать вдалеке куда важнее, чем писать вдалеке; вообще даже писать вдалеке -- это хулиганство какое-то (за некоторыми исключениями)

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

или она вообще не ставилась?

или модель затачивалась на "пишем куда угодно, читаем локально"?

вообще, жду рассказа про модель примерно такими словами, как я только что написал -- что макросы умеют, что неумеют, что не рассматривалось -- потому что то, что я читал, это какая-то конкретика, которая без общего взгляда мне совершенно не понятна

а да -- еще желательно кинуть ссылку на списочек макросов "как называется, че делает"

и еще вопрос -- а макросы умеют принимать в качестве аргумента название класса, или его поля? с проверкой на наличие? а если этого поля пока что нет, и оно будет дописано другим макросом?

например так:
  [StructuralEquality<exclude<StartPos>>, StructuralHashCode]
  public struct NToken
  {
    public StartPos : int { get; }
    public EndPos   : int { get; }
Re[15]: Тюринг-полные ли шаблоны C++?
От: m e  
Дата: 09.02.12 21:43
Оценка:
WH>Собственно вешание макро-атрибутов на класс это самый распространенный способ использования макросов которые что-то добавляют в типы.

насчет модели (в прошлом посте) -- скажем по 2-3 строчки про остальные 10 не столь распостраненных способов
(+ примерчик), и мне уже че-то будет ясно

или такой текст уже есть? тогда ссылку
Re[4]: Тюринг-полные ли шаблоны C++?
От: m e  
Дата: 09.02.12 22:41
Оценка:
в этой ветке я во всяком случае дальше собираюсь интересоваться только немерле

с++ я буду вспоминать только в том случае, если кто-то несправедливо скажет "а так в с++ нельзя" -- тогда приведу пример как можно

и на самом деле я был *неточен* -- да, меня интересуют недостатки с++, но недостатки с++ лучше всего мне расскажут пишущие плюсисты

хотя, конечно, если ты подробно ознакомился со стандартом с++11, тебя можно будет слушать о недостатках с++... но мне кажется ты не станешь знакомиться (и правильно

так что лучше про немерле
Re[14]: Тюринг-полные ли шаблоны C++?
От: FR  
Дата: 10.02.12 04:58
Оценка:
Здравствуйте, m e, Вы писали:

ME>при этом d-шный вариант выглядит приличнее, за исключением строки в миксине


Про D'шный вариант я чуть наврал, твое исходное

class T {
  int a;
  int b;
  int c;
  static if( hasMember!(X, "y") ) {
    int z;  
  }
}


тоже вполне нормально работает, меня ввел в заблуждение allMembers который для шаблонистых
классов чудит.

Ну и миксины вполне могут быть и не строковыми, а например и такими:

mixin template DeclareZ()
{
    int z;
}

class T {
  int a;
  int b;
  int c;
  static if( hasMember!(X, "y") ) {
    mixin DeclareZ;  
  }
}
Re[16]: Тюринг-полные ли шаблоны C++?
От: WolfHound  
Дата: 10.02.12 09:41
Оценка:
Здравствуйте, m e, Вы писали:

WH>>Ты попробуй найти класс по имени и туда что-то добавить.

WH>>Не можешь?
ME>навскидку не помню, можно ли перегрузить оператор -> снаружи класса
Даже если можно (сам забыл) то это ничего не меняет.
В класс ты ничего не добавишь.

>> Макросы Record, StructuralEquality, StructuralHashCode сразу получают TypeBuilder NToken'а. После чего достают из него поля. И генерируют на их основе нужные методы.

ME>1. тут идет дописывание, а не постройка с 0
А где я говорил обратное?

ME>2. про это я уже писал -- шаблоны, несмотря на тьюринг-полноту, просто не могут получить нужные данные

Они вообще мало что могут.
Это одна из причин по которой я бросил С++.

ME>"это" это https://github.com/rampelstinskin/ParserGenerator/blob/master/Test/Main.n ?

ME>ты давай опять словами, а то идея по коду не полностью восстанавливается
Это генератор парсеров основанный на новом алгоритме.
Кроме всего прочего умеет генерировать АСТ.
Вот использование этого АСТ
| CalcParser.Expr.Rounds(_, ast, _) => $"( $(printAst(ast)) )"
| CalcParser.Expr.Seq(_, asts, _)   => $<#{ ..$(asts; " ; "; printAst(_)) }#>
| CalcParser.Expr.Num(num)          => $"$num"
| CalcParser.Expr.Neg(_, v)         => $"[ - $(printAst(v)) ]"
| CalcParser.Expr.PrefixDec(_, v)   => $"[ -- $(printAst(v)) ]"
| CalcParser.Expr.PostfixDec(v, _)  => $"[ $(printAst(v)) -- ]"
| CalcParser.Expr.Add(l, _, r)      => $"[ $(printAst(l)) + $(printAst(r)) ]"
| CalcParser.Expr.Sub(l, _, r)      => $"[ $(printAst(l)) - $(printAst(r)) ]"
| CalcParser.Expr.Mul(l, _, r)      => $"[ $(printAst(l)) * $(printAst(r)) ]"
| CalcParser.Expr.Div(l, _, r)      => $"[ $(printAst(l)) / $(printAst(r)) ]"
| CalcParser.Expr.Mod(l, _, r)      => $"[ $(printAst(l)) % $(printAst(r)) ]"
| CalcParser.Expr.Pow(l, _, r)      => $"[ $(printAst(l)) ^ $(printAst(r)) ]"

| IncParser.Expr.Plus(_, v)         => $"[ + $(printAst(v)) ]"
| IncParser.Expr.PrefixInc(_, v)    => $"[ ++ $(printAst(v)) ]"
| IncParser.Expr.PostfixInc(v, _)   => $"[ $(printAst(v)) ++ ]"


ME>то, что я восстановил -- с точностью до тормозов лишнего виртуального вызова функции -- без проблем

И чем же ты собрался АСТ генерировать?
Да и тормозов у тебя будет намного больше, чем ты думаешь.
Посмотри на то, какая портянка получается. Получено ILSpy'ем.
И это проект еще не доделан. Когда закончу эта портянка, наверное, раза в два раздуется.
Обрати внимание сколько там классов.
  Скрытый текст
using Nemerle.Builtins;
using Nemerle.Collections;
using Nemerle.Core;
using Nemerle.Internal;
using Nemerle.Parser;
using Nemerle.Parser.Internal;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.CompilerServices;
internal abstract class CalcParser
{
    public sealed class GrammarImpl : CalcParser, IGrammar
    {
        public sealed class GrammarDescriptorImpl : GrammarDescriptor
        {
            public class _#postfix#_add_ : RuleDescriptor
            {
                private static readonly CalcParser.GrammarImpl.GrammarDescriptorImpl._#postfix#_add_ _staticDescriptor;
                public override string Name
                {
                    get
                    {
                        return "add";
                    }
                }
                public override GrammarDescriptor Grammar
                {
                    get
                    {
                        return CalcParser.GrammarImpl.StaticDescriptor;
                    }
                }
                public static RuleDescriptor StaticDescriptor
                {
                    get
                    {
                        return CalcParser.GrammarImpl.GrammarDescriptorImpl._#postfix#_add_._staticDescriptor;
                    }
                }
                static _#postfix#_add_()
                {
                    CalcParser.GrammarImpl.GrammarDescriptorImpl._#postfix#_add_._staticDescriptor = new CalcParser.GrammarImpl.GrammarDescriptorImpl._#postfix#_add_();
                }
                public CalcParser.Expr.Add ResultType()
                {
                    return null;
                }
                private _#postfix#_add_()
                {
                }
            }
            public class _#simple#__any_ : RuleDescriptor
            {
                private static readonly CalcParser.GrammarImpl.GrammarDescriptorImpl._#simple#__any_ _staticDescriptor;
                public override string Name
                {
                    get
                    {
                        return "any";
                    }
                }
                public override GrammarDescriptor Grammar
                {
                    get
                    {
                        return CalcParser.GrammarImpl.StaticDescriptor;
                    }
                }
                public static RuleDescriptor StaticDescriptor
                {
                    get
                    {
                        return CalcParser.GrammarImpl.GrammarDescriptorImpl._#simple#__any_._staticDescriptor;
                    }
                }
                static _#simple#__any_()
                {
                    CalcParser.GrammarImpl.GrammarDescriptorImpl._#simple#__any_._staticDescriptor = new CalcParser.GrammarImpl.GrammarDescriptorImpl._#simple#__any_();
                }
                private _#simple#__any_()
                {
                }
            }
            public class _#postfix#_div_ : RuleDescriptor
            {
                private static readonly CalcParser.GrammarImpl.GrammarDescriptorImpl._#postfix#_div_ _staticDescriptor;
                public override string Name
                {
                    get
                    {
                        return "div";
                    }
                }
                public override GrammarDescriptor Grammar
                {
                    get
                    {
                        return CalcParser.GrammarImpl.StaticDescriptor;
                    }
                }
                public static RuleDescriptor StaticDescriptor
                {
                    get
                    {
                        return CalcParser.GrammarImpl.GrammarDescriptorImpl._#postfix#_div_._staticDescriptor;
                    }
                }
                static _#postfix#_div_()
                {
                    CalcParser.GrammarImpl.GrammarDescriptorImpl._#postfix#_div_._staticDescriptor = new CalcParser.GrammarImpl.GrammarDescriptorImpl._#postfix#_div_();
                }
                public CalcParser.Expr.Div ResultType()
                {
                    return null;
                }
                private _#postfix#_div_()
                {
                }
            }
            public class _#point#___expr_ : RuleDescriptor
            {
                private static readonly CalcParser.GrammarImpl.GrammarDescriptorImpl._#point#___expr_ _staticDescriptor;
                public override string Name
                {
                    get
                    {
                        return "expr";
                    }
                }
                public override GrammarDescriptor Grammar
                {
                    get
                    {
                        return CalcParser.GrammarImpl.StaticDescriptor;
                    }
                }
                public static RuleDescriptor StaticDescriptor
                {
                    get
                    {
                        return CalcParser.GrammarImpl.GrammarDescriptorImpl._#point#___expr_._staticDescriptor;
                    }
                }
                static _#point#___expr_()
                {
                    CalcParser.GrammarImpl.GrammarDescriptorImpl._#point#___expr_._staticDescriptor = new CalcParser.GrammarImpl.GrammarDescriptorImpl._#point#___expr_();
                }
                public ExprAst ResultType()
                {
                    return null;
                }
                private _#point#___expr_()
                {
                }
            }
            public class _#postfix#_mod_ : RuleDescriptor
            {
                private static readonly CalcParser.GrammarImpl.GrammarDescriptorImpl._#postfix#_mod_ _staticDescriptor;
                public override string Name
                {
                    get
                    {
                        return "mod";
                    }
                }
                public override GrammarDescriptor Grammar
                {
                    get
                    {
                        return CalcParser.GrammarImpl.StaticDescriptor;
                    }
                }
                public static RuleDescriptor StaticDescriptor
                {
                    get
                    {
                        return CalcParser.GrammarImpl.GrammarDescriptorImpl._#postfix#_mod_._staticDescriptor;
                    }
                }
                static _#postfix#_mod_()
                {
                    CalcParser.GrammarImpl.GrammarDescriptorImpl._#postfix#_mod_._staticDescriptor = new CalcParser.GrammarImpl.GrammarDescriptorImpl._#postfix#_mod_();
                }
                public CalcParser.Expr.Mod ResultType()
                {
                    return null;
                }
                private _#postfix#_mod_()
                {
                }
            }
            public class _#postfix#_mul_ : RuleDescriptor
            {
                private static readonly CalcParser.GrammarImpl.GrammarDescriptorImpl._#postfix#_mul_ _staticDescriptor;
                public override string Name
                {
                    get
                    {
                        return "mul";
                    }
                }
                public override GrammarDescriptor Grammar
                {
                    get
                    {
                        return CalcParser.GrammarImpl.StaticDescriptor;
                    }
                }
                public static RuleDescriptor StaticDescriptor
                {
                    get
                    {
                        return CalcParser.GrammarImpl.GrammarDescriptorImpl._#postfix#_mul_._staticDescriptor;
                    }
                }
                static _#postfix#_mul_()
                {
                    CalcParser.GrammarImpl.GrammarDescriptorImpl._#postfix#_mul_._staticDescriptor = new CalcParser.GrammarImpl.GrammarDescriptorImpl._#postfix#_mul_();
                }
                public CalcParser.Expr.Mul ResultType()
                {
                    return null;
                }
                private _#postfix#_mul_()
                {
                }
            }
            public class _#prefix#__neg_ : RuleDescriptor
            {
                private static readonly CalcParser.GrammarImpl.GrammarDescriptorImpl._#prefix#__neg_ _staticDescriptor;
                public override string Name
                {
                    get
                    {
                        return "neg";
                    }
                }
                public override GrammarDescriptor Grammar
                {
                    get
                    {
                        return CalcParser.GrammarImpl.StaticDescriptor;
                    }
                }
                public static RuleDescriptor StaticDescriptor
                {
                    get
                    {
                        return CalcParser.GrammarImpl.GrammarDescriptorImpl._#prefix#__neg_._staticDescriptor;
                    }
                }
                static _#prefix#__neg_()
                {
                    CalcParser.GrammarImpl.GrammarDescriptorImpl._#prefix#__neg_._staticDescriptor = new CalcParser.GrammarImpl.GrammarDescriptorImpl._#prefix#__neg_();
                }
                public CalcParser.Expr.Neg ResultType()
                {
                    return null;
                }
                private _#prefix#__neg_()
                {
                }
            }
            public class _#prefix#__num_ : RuleDescriptor
            {
                private static readonly CalcParser.GrammarImpl.GrammarDescriptorImpl._#prefix#__num_ _staticDescriptor;
                public override string Name
                {
                    get
                    {
                        return "num";
                    }
                }
                public override GrammarDescriptor Grammar
                {
                    get
                    {
                        return CalcParser.GrammarImpl.StaticDescriptor;
                    }
                }
                public static RuleDescriptor StaticDescriptor
                {
                    get
                    {
                        return CalcParser.GrammarImpl.GrammarDescriptorImpl._#prefix#__num_._staticDescriptor;
                    }
                }
                static _#prefix#__num_()
                {
                    CalcParser.GrammarImpl.GrammarDescriptorImpl._#prefix#__num_._staticDescriptor = new CalcParser.GrammarImpl.GrammarDescriptorImpl._#prefix#__num_();
                }
                public CalcParser.Expr.Num ResultType()
                {
                    return null;
                }
                private _#prefix#__num_()
                {
                }
            }
            public class _#postfix#_postfixDec_ : RuleDescriptor
            {
                private static readonly CalcParser.GrammarImpl.GrammarDescriptorImpl._#postfix#_postfixDec_ _staticDescriptor;
                public override string Name
                {
                    get
                    {
                        return "postfixDec";
                    }
                }
                public override GrammarDescriptor Grammar
                {
                    get
                    {
                        return CalcParser.GrammarImpl.StaticDescriptor;
                    }
                }
                public static RuleDescriptor StaticDescriptor
                {
                    get
                    {
                        return CalcParser.GrammarImpl.GrammarDescriptorImpl._#postfix#_postfixDec_._staticDescriptor;
                    }
                }
                static _#postfix#_postfixDec_()
                {
                    CalcParser.GrammarImpl.GrammarDescriptorImpl._#postfix#_postfixDec_._staticDescriptor = new CalcParser.GrammarImpl.GrammarDescriptorImpl._#postfix#_postfixDec_();
                }
                public CalcParser.Expr.PostfixDec ResultType()
                {
                    return null;
                }
                private _#postfix#_postfixDec_()
                {
                }
            }
            public class _#postfix#_pow_ : RuleDescriptor
            {
                private static readonly CalcParser.GrammarImpl.GrammarDescriptorImpl._#postfix#_pow_ _staticDescriptor;
                public override string Name
                {
                    get
                    {
                        return "pow";
                    }
                }
                public override GrammarDescriptor Grammar
                {
                    get
                    {
                        return CalcParser.GrammarImpl.StaticDescriptor;
                    }
                }
                public static RuleDescriptor StaticDescriptor
                {
                    get
                    {
                        return CalcParser.GrammarImpl.GrammarDescriptorImpl._#postfix#_pow_._staticDescriptor;
                    }
                }
                static _#postfix#_pow_()
                {
                    CalcParser.GrammarImpl.GrammarDescriptorImpl._#postfix#_pow_._staticDescriptor = new CalcParser.GrammarImpl.GrammarDescriptorImpl._#postfix#_pow_();
                }
                public CalcParser.Expr.Pow ResultType()
                {
                    return null;
                }
                private _#postfix#_pow_()
                {
                }
            }
            public class _#prefix#__prefixDec_ : RuleDescriptor
            {
                private static readonly CalcParser.GrammarImpl.GrammarDescriptorImpl._#prefix#__prefixDec_ _staticDescriptor;
                public override string Name
                {
                    get
                    {
                        return "prefixDec";
                    }
                }
                public override GrammarDescriptor Grammar
                {
                    get
                    {
                        return CalcParser.GrammarImpl.StaticDescriptor;
                    }
                }
                public static RuleDescriptor StaticDescriptor
                {
                    get
                    {
                        return CalcParser.GrammarImpl.GrammarDescriptorImpl._#prefix#__prefixDec_._staticDescriptor;
                    }
                }
                static _#prefix#__prefixDec_()
                {
                    CalcParser.GrammarImpl.GrammarDescriptorImpl._#prefix#__prefixDec_._staticDescriptor = new CalcParser.GrammarImpl.GrammarDescriptorImpl._#prefix#__prefixDec_();
                }
                public CalcParser.Expr.PrefixDec ResultType()
                {
                    return null;
                }
                private _#prefix#__prefixDec_()
                {
                }
            }
            public class _#prefix#__rounds_ : RuleDescriptor
            {
                private static readonly CalcParser.GrammarImpl.GrammarDescriptorImpl._#prefix#__rounds_ _staticDescriptor;
                public override string Name
                {
                    get
                    {
                        return "rounds";
                    }
                }
                public override GrammarDescriptor Grammar
                {
                    get
                    {
                        return CalcParser.GrammarImpl.StaticDescriptor;
                    }
                }
                public static RuleDescriptor StaticDescriptor
                {
                    get
                    {
                        return CalcParser.GrammarImpl.GrammarDescriptorImpl._#prefix#__rounds_._staticDescriptor;
                    }
                }
                static _#prefix#__rounds_()
                {
                    CalcParser.GrammarImpl.GrammarDescriptorImpl._#prefix#__rounds_._staticDescriptor = new CalcParser.GrammarImpl.GrammarDescriptorImpl._#prefix#__rounds_();
                }
                public CalcParser.Expr.Rounds ResultType()
                {
                    return null;
                }
                private _#prefix#__rounds_()
                {
                }
            }
            public class _#simple#__s_ : RuleDescriptor
            {
                private static readonly CalcParser.GrammarImpl.GrammarDescriptorImpl._#simple#__s_ _staticDescriptor;
                public override string Name
                {
                    get
                    {
                        return "s";
                    }
                }
                public override GrammarDescriptor Grammar
                {
                    get
                    {
                        return CalcParser.GrammarImpl.StaticDescriptor;
                    }
                }
                public static RuleDescriptor StaticDescriptor
                {
                    get
                    {
                        return CalcParser.GrammarImpl.GrammarDescriptorImpl._#simple#__s_._staticDescriptor;
                    }
                }
                static _#simple#__s_()
                {
                    CalcParser.GrammarImpl.GrammarDescriptorImpl._#simple#__s_._staticDescriptor = new CalcParser.GrammarImpl.GrammarDescriptorImpl._#simple#__s_();
                }
                public void ResultType()
                {
                }
                private _#simple#__s_()
                {
                }
            }
            public class _#prefix#__seq_ : RuleDescriptor
            {
                private static readonly CalcParser.GrammarImpl.GrammarDescriptorImpl._#prefix#__seq_ _staticDescriptor;
                public override string Name
                {
                    get
                    {
                        return "seq";
                    }
                }
                public override GrammarDescriptor Grammar
                {
                    get
                    {
                        return CalcParser.GrammarImpl.StaticDescriptor;
                    }
                }
                public static RuleDescriptor StaticDescriptor
                {
                    get
                    {
                        return CalcParser.GrammarImpl.GrammarDescriptorImpl._#prefix#__seq_._staticDescriptor;
                    }
                }
                static _#prefix#__seq_()
                {
                    CalcParser.GrammarImpl.GrammarDescriptorImpl._#prefix#__seq_._staticDescriptor = new CalcParser.GrammarImpl.GrammarDescriptorImpl._#prefix#__seq_();
                }
                public CalcParser.Expr.Seq ResultType()
                {
                    return null;
                }
                private _#prefix#__seq_()
                {
                }
            }
            public class _#simple#__start_ : RuleDescriptor
            {
                private static readonly CalcParser.GrammarImpl.GrammarDescriptorImpl._#simple#__start_ _staticDescriptor;
                public override string Name
                {
                    get
                    {
                        return "start";
                    }
                }
                public override GrammarDescriptor Grammar
                {
                    get
                    {
                        return CalcParser.GrammarImpl.StaticDescriptor;
                    }
                }
                public static RuleDescriptor StaticDescriptor
                {
                    get
                    {
                        return CalcParser.GrammarImpl.GrammarDescriptorImpl._#simple#__start_._staticDescriptor;
                    }
                }
                static _#simple#__start_()
                {
                    CalcParser.GrammarImpl.GrammarDescriptorImpl._#simple#__start_._staticDescriptor = new CalcParser.GrammarImpl.GrammarDescriptorImpl._#simple#__start_();
                }
                public ExprAst ResultType()
                {
                    return null;
                }
                private _#simple#__start_()
                {
                }
            }
            public class _#postfix#_sub_ : RuleDescriptor
            {
                private static readonly CalcParser.GrammarImpl.GrammarDescriptorImpl._#postfix#_sub_ _staticDescriptor;
                public override string Name
                {
                    get
                    {
                        return "sub";
                    }
                }
                public override GrammarDescriptor Grammar
                {
                    get
                    {
                        return CalcParser.GrammarImpl.StaticDescriptor;
                    }
                }
                public static RuleDescriptor StaticDescriptor
                {
                    get
                    {
                        return CalcParser.GrammarImpl.GrammarDescriptorImpl._#postfix#_sub_._staticDescriptor;
                    }
                }
                static _#postfix#_sub_()
                {
                    CalcParser.GrammarImpl.GrammarDescriptorImpl._#postfix#_sub_._staticDescriptor = new CalcParser.GrammarImpl.GrammarDescriptorImpl._#postfix#_sub_();
                }
                public CalcParser.Expr.Sub ResultType()
                {
                    return null;
                }
                private _#postfix#_sub_()
                {
                }
            }
            public override GrammarDescriptor[] Dependencies
            {
                get
                {
                    return new GrammarDescriptor[]
                    {
                        NumParser.GrammarImpl.StaticDescriptor, 
                        IncParser.GrammarImpl.StaticDescriptor
                    };
                }
            }
            public override string Name
            {
                get
                {
                    return "CalcParser";
                }
            }
            public override string FullName
            {
                get
                {
                    return "CalcParser";
                }
            }
            public override IGrammar NewGrammar(Parser parser)
            {
                return new CalcParser.GrammarImpl(parser);
            }
            public override ParsingErrors NewParsingErrors()
            {
                return new CalcParser.GrammarImpl.ParsingErrorsImpl();
            }
        }
        private sealed class ParsingErrorsImpl : ParsingErrors
        {
            public int _#_sub_;
            public int _#_start_;
            public int _#_seq_;
            public int _#_s_;
            public int _#_rounds_;
            public int _#_prefixDec_;
            public int _#_pow_;
            public int _#_postfixDec_;
            public int _#_num_;
            public int _#_neg_;
            public int _#_mul_;
            public int _#_mod_;
            public int _#_expr_;
            public int _#_div_;
            public int _#_any_;
            public int _#_add_;
            public override void Clear()
            {
                this._#_add_ = -1;
                this._#_any_ = -1;
                this._#_div_ = -1;
                this._#_expr_ = -1;
                this._#_mod_ = -1;
                this._#_mul_ = -1;
                this._#_neg_ = -1;
                this._#_num_ = -1;
                this._#_postfixDec_ = -1;
                this._#_pow_ = -1;
                this._#_prefixDec_ = -1;
                this._#_rounds_ = -1;
                this._#_s_ = -1;
                this._#_seq_ = -1;
                this._#_start_ = -1;
                this._#_sub_ = -1;
            }
            public override void GetErrors(ref int pos, List<RuleDescriptor> descriptors)
            {
                int arg_04_0 = pos;
                if (pos < this._#_add_)
                {
                    pos = this._#_add_;
                    descriptors.Clear();
                }
                if (pos == this._#_add_)
                {
                    descriptors.Add(CalcParser.GrammarImpl.GrammarDescriptorImpl._#postfix#_add_.StaticDescriptor);
                }
                if (pos < this._#_any_)
                {
                    pos = this._#_any_;
                    descriptors.Clear();
                }
                if (pos == this._#_any_)
                {
                    descriptors.Add(CalcParser.GrammarImpl.GrammarDescriptorImpl._#simple#__any_.StaticDescriptor);
                }
                if (pos < this._#_div_)
                {
                    pos = this._#_div_;
                    descriptors.Clear();
                }
                if (pos == this._#_div_)
                {
                    descriptors.Add(CalcParser.GrammarImpl.GrammarDescriptorImpl._#postfix#_div_.StaticDescriptor);
                }
                if (pos < this._#_expr_)
                {
                    pos = this._#_expr_;
                    descriptors.Clear();
                }
                if (pos == this._#_expr_)
                {
                    descriptors.Add(CalcParser.GrammarImpl.GrammarDescriptorImpl._#point#___expr_.StaticDescriptor);
                }
                if (pos < this._#_mod_)
                {
                    pos = this._#_mod_;
                    descriptors.Clear();
                }
                if (pos == this._#_mod_)
                {
                    descriptors.Add(CalcParser.GrammarImpl.GrammarDescriptorImpl._#postfix#_mod_.StaticDescriptor);
                }
                if (pos < this._#_mul_)
                {
                    pos = this._#_mul_;
                    descriptors.Clear();
                }
                if (pos == this._#_mul_)
                {
                    descriptors.Add(CalcParser.GrammarImpl.GrammarDescriptorImpl._#postfix#_mul_.StaticDescriptor);
                }
                if (pos < this._#_neg_)
                {
                    pos = this._#_neg_;
                    descriptors.Clear();
                }
                if (pos == this._#_neg_)
                {
                    descriptors.Add(CalcParser.GrammarImpl.GrammarDescriptorImpl._#prefix#__neg_.StaticDescriptor);
                }
                if (pos < this._#_num_)
                {
                    pos = this._#_num_;
                    descriptors.Clear();
                }
                if (pos == this._#_num_)
                {
                    descriptors.Add(CalcParser.GrammarImpl.GrammarDescriptorImpl._#prefix#__num_.StaticDescriptor);
                }
                if (pos < this._#_postfixDec_)
                {
                    pos = this._#_postfixDec_;
                    descriptors.Clear();
                }
                if (pos == this._#_postfixDec_)
                {
                    descriptors.Add(CalcParser.GrammarImpl.GrammarDescriptorImpl._#postfix#_postfixDec_.StaticDescriptor);
                }
                if (pos < this._#_pow_)
                {
                    pos = this._#_pow_;
                    descriptors.Clear();
                }
                if (pos == this._#_pow_)
                {
                    descriptors.Add(CalcParser.GrammarImpl.GrammarDescriptorImpl._#postfix#_pow_.StaticDescriptor);
                }
                if (pos < this._#_prefixDec_)
                {
                    pos = this._#_prefixDec_;
                    descriptors.Clear();
                }
                if (pos == this._#_prefixDec_)
                {
                    descriptors.Add(CalcParser.GrammarImpl.GrammarDescriptorImpl._#prefix#__prefixDec_.StaticDescriptor);
                }
                if (pos < this._#_rounds_)
                {
                    pos = this._#_rounds_;
                    descriptors.Clear();
                }
                if (pos == this._#_rounds_)
                {
                    descriptors.Add(CalcParser.GrammarImpl.GrammarDescriptorImpl._#prefix#__rounds_.StaticDescriptor);
                }
                if (pos < this._#_s_)
                {
                    pos = this._#_s_;
                    descriptors.Clear();
                }
                if (pos == this._#_s_)
                {
                    descriptors.Add(CalcParser.GrammarImpl.GrammarDescriptorImpl._#simple#__s_.StaticDescriptor);
                }
                if (pos < this._#_seq_)
                {
                    pos = this._#_seq_;
                    descriptors.Clear();
                }
                if (pos == this._#_seq_)
                {
                    descriptors.Add(CalcParser.GrammarImpl.GrammarDescriptorImpl._#prefix#__seq_.StaticDescriptor);
                }
                if (pos < this._#_start_)
                {
                    pos = this._#_start_;
                    descriptors.Clear();
                }
                if (pos == this._#_start_)
                {
                    descriptors.Add(CalcParser.GrammarImpl.GrammarDescriptorImpl._#simple#__start_.StaticDescriptor);
                }
                if (pos < this._#_sub_)
                {
                    pos = this._#_sub_;
                    descriptors.Clear();
                }
                if (pos == this._#_sub_)
                {
                    descriptors.Add(CalcParser.GrammarImpl.GrammarDescriptorImpl._#postfix#_sub_.StaticDescriptor);
                }
            }
            public ParsingErrorsImpl()
            {
                this.Clear();
            }
        }
        private sealed class GrammarStateImpl : IGrammarState
        {
            private readonly ExtensionPostfixBase<ExprAst>[] _#_expr_PostfixRules_;
            private readonly ExtensionPrefixBase<ExprAst>[] _#_expr_PrefixRules__;
            [DebuggerBrowsable(DebuggerBrowsableState.Never), CompilerGenerated]
            private readonly CalcParser.GrammarImpl _N_Grammar_4132;
            public CalcParser.GrammarImpl Grammar
            {
                [CompilerGenerated]
                get
                {
                    return this._N_Grammar_4132;
                }
            }
            public void LoadThisState()
            {
                this.Grammar._#_expr_PrefixRules__ = this._#_expr_PrefixRules__;
                this.Grammar._#_expr_PostfixRules_ = this._#_expr_PostfixRules_;
            }
            public GrammarStateImpl(CalcParser.GrammarImpl grammar)
            {
                this._N_Grammar_4132 = grammar;
                this._#_expr_PrefixRules__ = this._N_Grammar_4132._#_expr_PrefixRules__;
                this._#_expr_PostfixRules_ = this._N_Grammar_4132._#_expr_PostfixRules_;
            }
            public GrammarStateImpl()
            {
            }
            IGrammar IGrammarState.get_Grammar()
            {
                return this.Grammar;
            }
        }
        public class _#postfix#_sub_ : ExtensionPostfixBase<ExprAst>
        {
            private readonly CalcParser.GrammarImpl _grammar;
            public override RuleDescriptor Descriptor
            {
                get
                {
                    return CalcParser.GrammarImpl.GrammarDescriptorImpl._#postfix#_sub_.StaticDescriptor;
                }
            }
            public override int Parse(int startPos, int pos, string text, int[] bestOffsets, ref ExprAst result)
            {
                bool isBest = false;
                NToken token_2 = default(NToken);
                ExprAst token_3 = null;
                ExprAst prefixResult = result;
                ExprAst token_4 = prefixResult;
                bool _N_cache_8663 = pos >= 0;
                bool arg_AA_0;
                if (_N_cache_8663)
                {
                    if (true)
                    {
                        if (isBest)
                        {
                            arg_AA_0 = true;
                        }
                        else
                        {
                            isBest = (bestOffsets[0] < pos);
                            arg_AA_0 = (isBest || bestOffsets[0] == pos);
                        }
                        goto IL_9F;
                    }
                }
                arg_AA_0 = false;
                IL_9F:
                int arg_36F_0;
                if (arg_AA_0)
                {
                    int arg_108_0;
                    if (pos < text.Length)
                    {
                        char c = text[pos];
                        arg_108_0 = ((c != '-') ? -1 : (pos + 1));
                    }
                    else
                    {
                        arg_108_0 = -1;
                    }
                    int newPos = arg_108_0;
                    if (newPos >= 0)
                    {
                        token_2 = new NToken(pos, newPos);
                    }
                    int pos2 = newPos;
                    bool _N_cache_8664 = pos2 >= 0;
                    bool arg_197_0;
                    if (_N_cache_8664)
                    {
                        if (true)
                        {
                            if (isBest)
                            {
                                arg_197_0 = true;
                            }
                            else
                            {
                                isBest = (bestOffsets[1] < pos2);
                                arg_197_0 = (isBest || bestOffsets[1] == pos2);
                            }
                            goto IL_18C;
                        }
                    }
                    arg_197_0 = false;
                    IL_18C:
                    if (arg_197_0)
                    {
                        int ofs = pos2;
                        int pos3 = this._grammar._#_s_(pos2, text);
                        bool _N_cache_8665 = pos3 >= 0;
                        bool arg_224_0;
                        if (_N_cache_8665)
                        {
                            if (true)
                            {
                                if (isBest)
                                {
                                    arg_224_0 = true;
                                }
                                else
                                {
                                    isBest = (bestOffsets[2] < pos3);
                                    arg_224_0 = (isBest || bestOffsets[2] == pos3);
                                }
                                goto IL_219;
                            }
                        }
                        arg_224_0 = false;
                        IL_219:
                        if (arg_224_0)
                        {
                            int ofs2 = pos3;
                            int pos4 = this._grammar._#_expr_(pos3, text, 10, ref token_3);
                            bool _N_cache_8666 = pos4 >= 0;
                            bool arg_2B5_0;
                            if (_N_cache_8666)
                            {
                                if (true)
                                {
                                    if (isBest)
                                    {
                                        arg_2B5_0 = true;
                                    }
                                    else
                                    {
                                        isBest = (bestOffsets[3] < pos4);
                                        arg_2B5_0 = (isBest || bestOffsets[3] == pos4);
                                    }
                                    goto IL_2AA;
                                }
                            }
                            arg_2B5_0 = false;
                            IL_2AA:
                            if (arg_2B5_0)
                            {
                                int ofs3 = pos4;
                                if (isBest)
                                {
                                    bestOffsets[0] = pos;
                                    bestOffsets[1] = ofs;
                                    bestOffsets[2] = ofs2;
                                    bestOffsets[3] = ofs3;
                                    int i = 4;
                                    while (i < bestOffsets.Length && bestOffsets[i] >= 0)
                                    {
                                        bestOffsets[i] = -1;
                                        i++;
                                    }
                                    arg_36F_0 = pos4;
                                }
                                else
                                {
                                    arg_36F_0 = -1;
                                }
                            }
                            else
                            {
                                arg_36F_0 = -1;
                            }
                        }
                        else
                        {
                            arg_36F_0 = -1;
                        }
                    }
                    else
                    {
                        arg_36F_0 = -1;
                    }
                }
                else
                {
                    arg_36F_0 = -1;
                }
                int newPos2 = arg_36F_0;
                if (newPos2 > 0)
                {
                    result = new CalcParser.Expr.Sub(token_4, token_2, token_3);
                    result.Location = new Location(this._grammar._parsingSource, token_4.StartPos, token_3.EndPos);
                }
                else
                {
                    if (this._grammar._parsingErrors._#_sub_ < pos)
                    {
                        this._grammar._parsingErrors._#_sub_ = pos;
                    }
                }
                return newPos2;
            }
            public _#postfix#_sub_(IGrammar grammar) : base(10, '\0', '?')
            {
                this._grammar = (CalcParser.GrammarImpl)grammar;
            }
        }
        public class _#prefix#__seq_ : ExtensionPrefixBase<ExprAst>
        {
            private readonly CalcParser.GrammarImpl _grammar;
            public override RuleDescriptor Descriptor
            {
                get
                {
                    return CalcParser.GrammarImpl.GrammarDescriptorImpl._#prefix#__seq_.StaticDescriptor;
                }
            }
            public override int Parse(int pos, string text, int[] bestOffsets, ref ExprAst result)
            {
                bool isBest = false;
                NToken token_ = default(NToken);
                list<ExprAst> token_2 = null;
                NToken token_3 = default(NToken);
                int arg_88_0;
                if (pos < text.Length)
                {
                    char c = text[pos];
                    arg_88_0 = ((c != '{') ? -1 : (pos + 1));
                }
                else
                {
                    arg_88_0 = -1;
                }
                int newPos = arg_88_0;
                if (newPos >= 0)
                {
                    token_ = new NToken(pos, newPos);
                }
                int pos2 = newPos;
                bool _N_cache_8962 = pos2 >= 0;
                bool arg_113_0;
                if (_N_cache_8962)
                {
                    if (true)
                    {
                        if (isBest)
                        {
                            arg_113_0 = true;
                        }
                        else
                        {
                            isBest = (bestOffsets[0] < pos2);
                            arg_113_0 = (isBest || bestOffsets[0] == pos2);
                        }
                        goto IL_108;
                    }
                }
                arg_113_0 = false;
                IL_108:
                int arg_4C6_0;
                if (arg_113_0)
                {
                    int ofs0 = pos2;
                    int pos3 = this._grammar._#_s_(pos2, text);
                    bool _N_cache_8963 = pos3 >= 0;
                    bool arg_19E_0;
                    if (_N_cache_8963)
                    {
                        if (true)
                        {
                            if (isBest)
                            {
                                arg_19E_0 = true;
                            }
                            else
                            {
                                isBest = (bestOffsets[1] < pos3);
                                arg_19E_0 = (isBest || bestOffsets[1] == pos3);
                            }
                            goto IL_193;
                        }
                    }
                    arg_19E_0 = false;
                    IL_193:
                    if (arg_19E_0)
                    {
                        int ofs = pos3;
                        List<ExprAst> tmpList = new List<ExprAst>();
                        ExprAst token_4 = null;
                        int num = pos3;
                        while (true)
                        {
                            int newPos2 = this._grammar._#_expr_(num, text, 0, ref token_4);
                            if (newPos2 < 0)
                            {
                                break;
                            }
                            tmpList.Add(token_4);
                            num = newPos2;
                        }
                        int newPos3 = num;
                        token_2 = tmpList.NToList<ExprAst>();
                        int pos4 = newPos3;
                        bool _N_cache_8964 = pos4 >= 0;
                        bool arg_28A_0;
                        if (_N_cache_8964)
                        {
                            if (true)
                            {
                                if (isBest)
                                {
                                    arg_28A_0 = true;
                                }
                                else
                                {
                                    isBest = (bestOffsets[2] < pos4);
                                    arg_28A_0 = (isBest || bestOffsets[2] == pos4);
                                }
                                goto IL_27F;
                            }
                        }
                        arg_28A_0 = false;
                        IL_27F:
                        if (arg_28A_0)
                        {
                            int ofs2 = pos4;
                            int arg_2E8_0;
                            if (pos4 < text.Length)
                            {
                                char c = text[pos4];
                                arg_2E8_0 = ((c != '}') ? -1 : (pos4 + 1));
                            }
                            else
                            {
                                arg_2E8_0 = -1;
                            }
                            int newPos4 = arg_2E8_0;
                            if (newPos4 >= 0)
                            {
                                token_3 = new NToken(pos4, newPos4);
                            }
                            int pos5 = newPos4;
                            bool _N_cache_8965 = pos5 >= 0;
                            bool arg_375_0;
                            if (_N_cache_8965)
                            {
                                if (true)
                                {
                                    if (isBest)
                                    {
                                        arg_375_0 = true;
                                    }
                                    else
                                    {
                                        isBest = (bestOffsets[3] < pos5);
                                        arg_375_0 = (isBest || bestOffsets[3] == pos5);
                                    }
                                    goto IL_36A;
                                }
                            }
                            arg_375_0 = false;
                            IL_36A:
                            if (arg_375_0)
                            {
                                int ofs3 = pos5;
                                int pos6 = this._grammar._#_s_(pos5, text);
                                bool _N_cache_8966 = pos6 >= 0;
                                bool arg_400_0;
                                if (_N_cache_8966)
                                {
                                    if (true)
                                    {
                                        if (isBest)
                                        {
                                            arg_400_0 = true;
                                        }
                                        else
                                        {
                                            isBest = (bestOffsets[4] < pos6);
                                            arg_400_0 = (isBest || bestOffsets[4] == pos6);
                                        }
                                        goto IL_3F5;
                                    }
                                }
                                arg_400_0 = false;
                                IL_3F5:
                                if (arg_400_0)
                                {
                                    int ofs4 = pos6;
                                    if (isBest)
                                    {
                                        bestOffsets[0] = ofs0;
                                        bestOffsets[1] = ofs;
                                        bestOffsets[2] = ofs2;
                                        bestOffsets[3] = ofs3;
                                        bestOffsets[4] = ofs4;
                                        int i = 5;
                                        while (i < bestOffsets.Length && bestOffsets[i] >= 0)
                                        {
                                            bestOffsets[i] = -1;
                                            i++;
                                        }
                                        arg_4C6_0 = pos6;
                                    }
                                    else
                                    {
                                        arg_4C6_0 = -1;
                                    }
                                }
                                else
                                {
                                    arg_4C6_0 = -1;
                                }
                            }
                            else
                            {
                                arg_4C6_0 = -1;
                            }
                        }
                        else
                        {
                            arg_4C6_0 = -1;
                        }
                    }
                    else
                    {
                        arg_4C6_0 = -1;
                    }
                }
                else
                {
                    arg_4C6_0 = -1;
                }
                int newPos5 = arg_4C6_0;
                if (newPos5 > 0)
                {
                    result = new CalcParser.Expr.Seq(token_, token_2, token_3);
                    result.Location = new Location(this._grammar._parsingSource, token_.StartPos, token_3.EndPos);
                }
                else
                {
                    if (this._grammar._parsingErrors._#_seq_ < pos)
                    {
                        this._grammar._parsingErrors._#_seq_ = pos;
                    }
                }
                return newPos5;
            }
            public _#prefix#__seq_(IGrammar grammar) : base('\0', '?')
            {
                this._grammar = (CalcParser.GrammarImpl)grammar;
            }
        }
        public class _#prefix#__rounds_ : ExtensionPrefixBase<ExprAst>
        {
            private readonly CalcParser.GrammarImpl _grammar;
            public override RuleDescriptor Descriptor
            {
                get
                {
                    return CalcParser.GrammarImpl.GrammarDescriptorImpl._#prefix#__rounds_.StaticDescriptor;
                }
            }
            public override int Parse(int pos, string text, int[] bestOffsets, ref ExprAst result)
            {
                bool isBest = false;
                NToken token_ = default(NToken);
                ExprAst token_2 = null;
                NToken token_3 = default(NToken);
                int arg_88_0;
                if (pos < text.Length)
                {
                    char c = text[pos];
                    arg_88_0 = ((c != '(') ? -1 : (pos + 1));
                }
                else
                {
                    arg_88_0 = -1;
                }
                int newPos = arg_88_0;
                if (newPos >= 0)
                {
                    token_ = new NToken(pos, newPos);
                }
                int pos2 = newPos;
                bool _N_cache_9115 = pos2 >= 0;
                bool arg_113_0;
                if (_N_cache_9115)
                {
                    if (true)
                    {
                        if (isBest)
                        {
                            arg_113_0 = true;
                        }
                        else
                        {
                            isBest = (bestOffsets[0] < pos2);
                            arg_113_0 = (isBest || bestOffsets[0] == pos2);
                        }
                        goto IL_108;
                    }
                }
                arg_113_0 = false;
                IL_108:
                int arg_468_0;
                if (arg_113_0)
                {
                    int ofs0 = pos2;
                    int pos3 = this._grammar._#_s_(pos2, text);
                    bool _N_cache_9116 = pos3 >= 0;
                    bool arg_19E_0;
                    if (_N_cache_9116)
                    {
                        if (true)
                        {
                            if (isBest)
                            {
                                arg_19E_0 = true;
                            }
                            else
                            {
                                isBest = (bestOffsets[1] < pos3);
                                arg_19E_0 = (isBest || bestOffsets[1] == pos3);
                            }
                            goto IL_193;
                        }
                    }
                    arg_19E_0 = false;
                    IL_193:
                    if (arg_19E_0)
                    {
                        int ofs = pos3;
                        int pos4 = this._grammar._#_expr_(pos3, text, 0, ref token_2);
                        bool _N_cache_9117 = pos4 >= 0;
                        bool arg_22C_0;
                        if (_N_cache_9117)
                        {
                            if (true)
                            {
                                if (isBest)
                                {
                                    arg_22C_0 = true;
                                }
                                else
                                {
                                    isBest = (bestOffsets[2] < pos4);
                                    arg_22C_0 = (isBest || bestOffsets[2] == pos4);
                                }
                                goto IL_221;
                            }
                        }
                        arg_22C_0 = false;
                        IL_221:
                        if (arg_22C_0)
                        {
                            int ofs2 = pos4;
                            int arg_28A_0;
                            if (pos4 < text.Length)
                            {
                                char c = text[pos4];
                                arg_28A_0 = ((c != ')') ? -1 : (pos4 + 1));
                            }
                            else
                            {
                                arg_28A_0 = -1;
                            }
                            int newPos2 = arg_28A_0;
                            if (newPos2 >= 0)
                            {
                                token_3 = new NToken(pos4, newPos2);
                            }
                            int pos5 = newPos2;
                            bool _N_cache_9118 = pos5 >= 0;
                            bool arg_317_0;
                            if (_N_cache_9118)
                            {
                                if (true)
                                {
                                    if (isBest)
                                    {
                                        arg_317_0 = true;
                                    }
                                    else
                                    {
                                        isBest = (bestOffsets[3] < pos5);
                                        arg_317_0 = (isBest || bestOffsets[3] == pos5);
                                    }
                                    goto IL_30C;
                                }
                            }
                            arg_317_0 = false;
                            IL_30C:
                            if (arg_317_0)
                            {
                                int ofs3 = pos5;
                                int pos6 = this._grammar._#_s_(pos5, text);
                                bool _N_cache_9119 = pos6 >= 0;
                                bool arg_3A2_0;
                                if (_N_cache_9119)
                                {
                                    if (true)
                                    {
                                        if (isBest)
                                        {
                                            arg_3A2_0 = true;
                                        }
                                        else
                                        {
                                            isBest = (bestOffsets[4] < pos6);
                                            arg_3A2_0 = (isBest || bestOffsets[4] == pos6);
                                        }
                                        goto IL_397;
                                    }
                                }
                                arg_3A2_0 = false;
                                IL_397:
                                if (arg_3A2_0)
                                {
                                    int ofs4 = pos6;
                                    if (isBest)
                                    {
                                        bestOffsets[0] = ofs0;
                                        bestOffsets[1] = ofs;
                                        bestOffsets[2] = ofs2;
                                        bestOffsets[3] = ofs3;
                                        bestOffsets[4] = ofs4;
                                        int i = 5;
                                        while (i < bestOffsets.Length && bestOffsets[i] >= 0)
                                        {
                                            bestOffsets[i] = -1;
                                            i++;
                                        }
                                        arg_468_0 = pos6;
                                    }
                                    else
                                    {
                                        arg_468_0 = -1;
                                    }
                                }
                                else
                                {
                                    arg_468_0 = -1;
                                }
                            }
                            else
                            {
                                arg_468_0 = -1;
                            }
                        }
                        else
                        {
                            arg_468_0 = -1;
                        }
                    }
                    else
                    {
                        arg_468_0 = -1;
                    }
                }
                else
                {
                    arg_468_0 = -1;
                }
                int newPos3 = arg_468_0;
                if (newPos3 > 0)
                {
                    result = new CalcParser.Expr.Rounds(token_, token_2, token_3);
                    result.Location = new Location(this._grammar._parsingSource, token_.StartPos, token_3.EndPos);
                }
                else
                {
                    if (this._grammar._parsingErrors._#_rounds_ < pos)
                    {
                        this._grammar._parsingErrors._#_rounds_ = pos;
                    }
                }
                return newPos3;
            }
            public _#prefix#__rounds_(IGrammar grammar) : base('\0', '?')
            {
                this._grammar = (CalcParser.GrammarImpl)grammar;
            }
        }
        public class _#prefix#__prefixDec_ : ExtensionPrefixBase<ExprAst>
        {
            private readonly CalcParser.GrammarImpl _grammar;
            public override RuleDescriptor Descriptor
            {
                get
                {
                    return CalcParser.GrammarImpl.GrammarDescriptorImpl._#prefix#__prefixDec_.StaticDescriptor;
                }
            }
            public override int Parse(int pos, string text, int[] bestOffsets, ref ExprAst result)
            {
                bool isBest = false;
                NToken token_ = default(NToken);
                ExprAst token_2 = null;
                int newPos = (pos + 1 >= text.Length || text[pos] != '-' || text[pos + 1] != '-') ? -1 : (pos + 2);
                if (newPos >= 0)
                {
                    token_ = new NToken(pos, newPos);
                }
                int pos2 = newPos;
                bool _N_cache_9259 = pos2 >= 0;
                bool arg_117_0;
                if (_N_cache_9259)
                {
                    if (true)
                    {
                        if (isBest)
                        {
                            arg_117_0 = true;
                        }
                        else
                        {
                            isBest = (bestOffsets[0] < pos2);
                            arg_117_0 = (isBest || bestOffsets[0] == pos2);
                        }
                        goto IL_10C;
                    }
                }
                arg_117_0 = false;
                IL_10C:
                int arg_2D6_0;
                if (arg_117_0)
                {
                    int ofs0 = pos2;
                    int pos3 = this._grammar._#_s_(pos2, text);
                    bool _N_cache_9260 = pos3 >= 0;
                    bool arg_1A2_0;
                    if (_N_cache_9260)
                    {
                        if (true)
                        {
                            if (isBest)
                            {
                                arg_1A2_0 = true;
                            }
                            else
                            {
                                isBest = (bestOffsets[1] < pos3);
                                arg_1A2_0 = (isBest || bestOffsets[1] == pos3);
                            }
                            goto IL_197;
                        }
                    }
                    arg_1A2_0 = false;
                    IL_197:
                    if (arg_1A2_0)
                    {
                        int ofs = pos3;
                        int pos4 = this._grammar._#_expr_(pos3, text, 200, ref token_2);
                        bool _N_cache_9261 = pos4 >= 0;
                        bool arg_234_0;
                        if (_N_cache_9261)
                        {
                            if (true)
                            {
                                if (isBest)
                                {
                                    arg_234_0 = true;
                                }
                                else
                                {
                                    isBest = (bestOffsets[2] < pos4);
                                    arg_234_0 = (isBest || bestOffsets[2] == pos4);
                                }
                                goto IL_229;
                            }
                        }
                        arg_234_0 = false;
                        IL_229:
                        if (arg_234_0)
                        {
                            int ofs2 = pos4;
                            if (isBest)
                            {
                                bestOffsets[0] = ofs0;
                                bestOffsets[1] = ofs;
                                bestOffsets[2] = ofs2;
                                int i = 3;
                                while (i < bestOffsets.Length && bestOffsets[i] >= 0)
                                {
                                    bestOffsets[i] = -1;
                                    i++;
                                }
                                arg_2D6_0 = pos4;
                            }
                            else
                            {
                                arg_2D6_0 = -1;
                            }
                        }
                        else
                        {
                            arg_2D6_0 = -1;
                        }
                    }
                    else
                    {
                        arg_2D6_0 = -1;
                    }
                }
                else
                {
                    arg_2D6_0 = -1;
                }
                int newPos2 = arg_2D6_0;
                if (newPos2 > 0)
                {
                    result = new CalcParser.Expr.PrefixDec(token_, token_2);
                    result.Location = new Location(this._grammar._parsingSource, token_.StartPos, token_2.EndPos);
                }
                else
                {
                    if (this._grammar._parsingErrors._#_prefixDec_ < pos)
                    {
                        this._grammar._parsingErrors._#_prefixDec_ = pos;
                    }
                }
                return newPos2;
            }
            public _#prefix#__prefixDec_(IGrammar grammar) : base('\0', '?')
            {
                this._grammar = (CalcParser.GrammarImpl)grammar;
            }
        }
        public class _#postfix#_pow_ : ExtensionPostfixBase<ExprAst>
        {
            private readonly CalcParser.GrammarImpl _grammar;
            public override RuleDescriptor Descriptor
            {
                get
                {
                    return CalcParser.GrammarImpl.GrammarDescriptorImpl._#postfix#_pow_.StaticDescriptor;
                }
            }
            public override int Parse(int startPos, int pos, string text, int[] bestOffsets, ref ExprAst result)
            {
                bool isBest = false;
                NToken token_2 = default(NToken);
                ExprAst token_3 = null;
                ExprAst prefixResult = result;
                ExprAst token_4 = prefixResult;
                bool _N_cache_9359 = pos >= 0;
                bool arg_AA_0;
                if (_N_cache_9359)
                {
                    if (true)
                    {
                        if (isBest)
                        {
                            arg_AA_0 = true;
                        }
                        else
                        {
                            isBest = (bestOffsets[0] < pos);
                            arg_AA_0 = (isBest || bestOffsets[0] == pos);
                        }
                        goto IL_9F;
                    }
                }
                arg_AA_0 = false;
                IL_9F:
                int arg_36F_0;
                if (arg_AA_0)
                {
                    int arg_108_0;
                    if (pos < text.Length)
                    {
                        char c = text[pos];
                        arg_108_0 = ((c != '^') ? -1 : (pos + 1));
                    }
                    else
                    {
                        arg_108_0 = -1;
                    }
                    int newPos = arg_108_0;
                    if (newPos >= 0)
                    {
                        token_2 = new NToken(pos, newPos);
                    }
                    int pos2 = newPos;
                    bool _N_cache_9360 = pos2 >= 0;
                    bool arg_197_0;
                    if (_N_cache_9360)
                    {
                        if (true)
                        {
                            if (isBest)
                            {
                                arg_197_0 = true;
                            }
                            else
                            {
                                isBest = (bestOffsets[1] < pos2);
                                arg_197_0 = (isBest || bestOffsets[1] == pos2);
                            }
                            goto IL_18C;
                        }
                    }
                    arg_197_0 = false;
                    IL_18C:
                    if (arg_197_0)
                    {
                        int ofs = pos2;
                        int pos3 = this._grammar._#_s_(pos2, text);
                        bool _N_cache_9361 = pos3 >= 0;
                        bool arg_224_0;
                        if (_N_cache_9361)
                        {
                            if (true)
                            {
                                if (isBest)
                                {
                                    arg_224_0 = true;
                                }
                                else
                                {
                                    isBest = (bestOffsets[2] < pos3);
                                    arg_224_0 = (isBest || bestOffsets[2] == pos3);
                                }
                                goto IL_219;
                            }
                        }
                        arg_224_0 = false;
                        IL_219:
                        if (arg_224_0)
                        {
                            int ofs2 = pos3;
                            int pos4 = this._grammar._#_expr_(pos3, text, 30, ref token_3);
                            bool _N_cache_9362 = pos4 >= 0;
                            bool arg_2B5_0;
                            if (_N_cache_9362)
                            {
                                if (true)
                                {
                                    if (isBest)
                                    {
                                        arg_2B5_0 = true;
                                    }
                                    else
                                    {
                                        isBest = (bestOffsets[3] < pos4);
                                        arg_2B5_0 = (isBest || bestOffsets[3] == pos4);
                                    }
                                    goto IL_2AA;
                                }
                            }
                            arg_2B5_0 = false;
                            IL_2AA:
                            if (arg_2B5_0)
                            {
                                int ofs3 = pos4;
                                if (isBest)
                                {
                                    bestOffsets[0] = pos;
                                    bestOffsets[1] = ofs;
                                    bestOffsets[2] = ofs2;
                                    bestOffsets[3] = ofs3;
                                    int i = 4;
                                    while (i < bestOffsets.Length && bestOffsets[i] >= 0)
                                    {
                                        bestOffsets[i] = -1;
                                        i++;
                                    }
                                    arg_36F_0 = pos4;
                                }
                                else
                                {
                                    arg_36F_0 = -1;
                                }
                            }
                            else
                            {
                                arg_36F_0 = -1;
                            }
                        }
                        else
                        {
                            arg_36F_0 = -1;
                        }
                    }
                    else
                    {
                        arg_36F_0 = -1;
                    }
                }
                else
                {
                    arg_36F_0 = -1;
                }
                int newPos2 = arg_36F_0;
                if (newPos2 > 0)
                {
                    result = new CalcParser.Expr.Pow(token_4, token_2, token_3);
                    result.Location = new Location(this._grammar._parsingSource, token_4.StartPos, token_3.EndPos);
                }
                else
                {
                    if (this._grammar._parsingErrors._#_pow_ < pos)
                    {
                        this._grammar._parsingErrors._#_pow_ = pos;
                    }
                }
                return newPos2;
            }
            public _#postfix#_pow_(IGrammar grammar) : base(31, '\0', '?')
            {
                this._grammar = (CalcParser.GrammarImpl)grammar;
            }
        }
        public class _#postfix#_postfixDec_ : ExtensionPostfixBase<ExprAst>
        {
            private readonly CalcParser.GrammarImpl _grammar;
            public override RuleDescriptor Descriptor
            {
                get
                {
                    return CalcParser.GrammarImpl.GrammarDescriptorImpl._#postfix#_postfixDec_.StaticDescriptor;
                }
            }
            public override int Parse(int startPos, int pos, string text, int[] bestOffsets, ref ExprAst result)
            {
                bool isBest = false;
                NToken token_2 = default(NToken);
                ExprAst prefixResult = result;
                ExprAst token_3 = prefixResult;
                bool _N_cache_9478 = pos >= 0;
                bool arg_A6_0;
                if (_N_cache_9478)
                {
                    if (true)
                    {
                        if (isBest)
                        {
                            arg_A6_0 = true;
                        }
                        else
                        {
                            isBest = (bestOffsets[0] < pos);
                            arg_A6_0 = (isBest || bestOffsets[0] == pos);
                        }
                        goto IL_9B;
                    }
                }
                arg_A6_0 = false;
                IL_9B:
                int arg_2D9_0;
                if (arg_A6_0)
                {
                    int newPos = (pos + 1 >= text.Length || text[pos] != '-' || text[pos + 1] != '-') ? -1 : (pos + 2);
                    if (newPos >= 0)
                    {
                        token_2 = new NToken(pos, newPos);
                    }
                    int pos2 = newPos;
                    bool _N_cache_9479 = pos2 >= 0;
                    bool arg_1A5_0;
                    if (_N_cache_9479)
                    {
                        if (true)
                        {
                            if (isBest)
                            {
                                arg_1A5_0 = true;
                            }
                            else
                            {
                                isBest = (bestOffsets[1] < pos2);
                                arg_1A5_0 = (isBest || bestOffsets[1] == pos2);
                            }
                            goto IL_19A;
                        }
                    }
                    arg_1A5_0 = false;
                    IL_19A:
                    if (arg_1A5_0)
                    {
                        int ofs = pos2;
                        int pos3 = this._grammar._#_s_(pos2, text);
                        bool _N_cache_9480 = pos3 >= 0;
                        bool arg_232_0;
                        if (_N_cache_9480)
                        {
                            if (true)
                            {
                                if (isBest)
                                {
                                    arg_232_0 = true;
                                }
                                else
                                {
                                    isBest = (bestOffsets[2] < pos3);
                                    arg_232_0 = (isBest || bestOffsets[2] == pos3);
                                }
                                goto IL_227;
                            }
                        }
                        arg_232_0 = false;
                        IL_227:
                        if (arg_232_0)
                        {
                            int ofs2 = pos3;
                            if (isBest)
                            {
                                bestOffsets[0] = pos;
                                bestOffsets[1] = ofs;
                                bestOffsets[2] = ofs2;
                                int i = 3;
                                while (i < bestOffsets.Length && bestOffsets[i] >= 0)
                                {
                                    bestOffsets[i] = -1;
                                    i++;
                                }
                                arg_2D9_0 = pos3;
                            }
                            else
                            {
                                arg_2D9_0 = -1;
                            }
                        }
                        else
                        {
                            arg_2D9_0 = -1;
                        }
                    }
                    else
                    {
                        arg_2D9_0 = -1;
                    }
                }
                else
                {
                    arg_2D9_0 = -1;
                }
                int newPos2 = arg_2D9_0;
                if (newPos2 > 0)
                {
                    result = new CalcParser.Expr.PostfixDec(token_3, token_2);
                    result.Location = new Location(this._grammar._parsingSource, token_3.StartPos, token_2.EndPos);
                }
                else
                {
                    if (this._grammar._parsingErrors._#_postfixDec_ < pos)
                    {
                        this._grammar._parsingErrors._#_postfixDec_ = pos;
                    }
                }
                return newPos2;
            }
            public _#postfix#_postfixDec_(IGrammar grammar) : base(200, '\0', '?')
            {
                this._grammar = (CalcParser.GrammarImpl)grammar;
            }
        }
        public class _#prefix#__num_ : ExtensionPrefixBase<ExprAst>
        {
            private readonly CalcParser.GrammarImpl _grammar;
            public override RuleDescriptor Descriptor
            {
                get
                {
                    return CalcParser.GrammarImpl.GrammarDescriptorImpl._#prefix#__num_.StaticDescriptor;
                }
            }
            public override int Parse(int pos, string text, int[] bestOffsets, ref ExprAst result)
            {
                bool isBest = false;
                string token_ = null;
                int pos2 = this._grammar._#grammar#1._#_number_(pos, text, ref token_);
                bool _N_cache_9580 = pos2 >= 0;
                bool arg_A1_0;
                if (_N_cache_9580)
                {
                    if (true)
                    {
                        if (isBest)
                        {
                            arg_A1_0 = true;
                        }
                        else
                        {
                            isBest = (bestOffsets[0] < pos2);
                            arg_A1_0 = (isBest || bestOffsets[0] == pos2);
                        }
                        goto IL_96;
                    }
                }
                arg_A1_0 = false;
                IL_96:
                int arg_1BA_0;
                if (arg_A1_0)
                {
                    int ofs0 = pos2;
                    int pos3 = this._grammar._#_s_(pos2, text);
                    bool _N_cache_9581 = pos3 >= 0;
                    bool arg_12A_0;
                    if (_N_cache_9581)
                    {
                        if (true)
                        {
                            if (isBest)
                            {
                                arg_12A_0 = true;
                            }
                            else
                            {
                                isBest = (bestOffsets[1] < pos3);
                                arg_12A_0 = (isBest || bestOffsets[1] == pos3);
                            }
                            goto IL_11F;
                        }
                    }
                    arg_12A_0 = false;
                    IL_11F:
                    if (arg_12A_0)
                    {
                        int ofs = pos3;
                        if (isBest)
                        {
                            bestOffsets[0] = ofs0;
                            bestOffsets[1] = ofs;
                            int i = 2;
                            while (i < bestOffsets.Length && bestOffsets[i] >= 0)
                            {
                                bestOffsets[i] = -1;
                                i++;
                            }
                            arg_1BA_0 = pos3;
                        }
                        else
                        {
                            arg_1BA_0 = -1;
                        }
                    }
                    else
                    {
                        arg_1BA_0 = -1;
                    }
                }
                else
                {
                    arg_1BA_0 = -1;
                }
                int newPos = arg_1BA_0;
                if (newPos > 0)
                {
                    result = new CalcParser.Expr.Num(token_);
                    result.Location = new Location(this._grammar._parsingSource, pos, newPos);
                }
                else
                {
                    if (this._grammar._parsingErrors._#_num_ < pos)
                    {
                        this._grammar._parsingErrors._#_num_ = pos;
                    }
                }
                return newPos;
            }
            public _#prefix#__num_(IGrammar grammar) : base('\0', '?')
            {
                this._grammar = (CalcParser.GrammarImpl)grammar;
            }
        }
        public class _#prefix#__neg_ : ExtensionPrefixBase<ExprAst>
        {
            private readonly CalcParser.GrammarImpl _grammar;
            public override RuleDescriptor Descriptor
            {
                get
                {
                    return CalcParser.GrammarImpl.GrammarDescriptorImpl._#prefix#__neg_.StaticDescriptor;
                }
            }
            public override int Parse(int pos, string text, int[] bestOffsets, ref ExprAst result)
            {
                bool isBest = false;
                NToken token_ = default(NToken);
                ExprAst token_2 = null;
                int arg_7B_0;
                if (pos < text.Length)
                {
                    char c = text[pos];
                    arg_7B_0 = ((c != '-') ? -1 : (pos + 1));
                }
                else
                {
                    arg_7B_0 = -1;
                }
                int newPos = arg_7B_0;
                if (newPos >= 0)
                {
                    token_ = new NToken(pos, newPos);
                }
                int pos2 = newPos;
                bool _N_cache_9670 = pos2 >= 0;
                bool arg_106_0;
                if (_N_cache_9670)
                {
                    if (true)
                    {
                        if (isBest)
                        {
                            arg_106_0 = true;
                        }
                        else
                        {
                            isBest = (bestOffsets[0] < pos2);
                            arg_106_0 = (isBest || bestOffsets[0] == pos2);
                        }
                        goto IL_FB;
                    }
                }
                arg_106_0 = false;
                IL_FB:
                int arg_2C2_0;
                if (arg_106_0)
                {
                    int ofs0 = pos2;
                    int pos3 = this._grammar._#_s_(pos2, text);
                    bool _N_cache_9671 = pos3 >= 0;
                    bool arg_191_0;
                    if (_N_cache_9671)
                    {
                        if (true)
                        {
                            if (isBest)
                            {
                                arg_191_0 = true;
                            }
                            else
                            {
                                isBest = (bestOffsets[1] < pos3);
                                arg_191_0 = (isBest || bestOffsets[1] == pos3);
                            }
                            goto IL_186;
                        }
                    }
                    arg_191_0 = false;
                    IL_186:
                    if (arg_191_0)
                    {
                        int ofs = pos3;
                        int pos4 = this._grammar._#_expr_(pos3, text, 100, ref token_2);
                        bool _N_cache_9672 = pos4 >= 0;
                        bool arg_220_0;
                        if (_N_cache_9672)
                        {
                            if (true)
                            {
                                if (isBest)
                                {
                                    arg_220_0 = true;
                                }
                                else
                                {
                                    isBest = (bestOffsets[2] < pos4);
                                    arg_220_0 = (isBest || bestOffsets[2] == pos4);
                                }
                                goto IL_215;
                            }
                        }
                        arg_220_0 = false;
                        IL_215:
                        if (arg_220_0)
                        {
                            int ofs2 = pos4;
                            if (isBest)
                            {
                                bestOffsets[0] = ofs0;
                                bestOffsets[1] = ofs;
                                bestOffsets[2] = ofs2;
                                int i = 3;
                                while (i < bestOffsets.Length && bestOffsets[i] >= 0)
                                {
                                    bestOffsets[i] = -1;
                                    i++;
                                }
                                arg_2C2_0 = pos4;
                            }
                            else
                            {
                                arg_2C2_0 = -1;
                            }
                        }
                        else
                        {
                            arg_2C2_0 = -1;
                        }
                    }
                    else
                    {
                        arg_2C2_0 = -1;
                    }
                }
                else
                {
                    arg_2C2_0 = -1;
                }
                int newPos2 = arg_2C2_0;
                if (newPos2 > 0)
                {
                    result = new CalcParser.Expr.Neg(token_, token_2);
                    result.Location = new Location(this._grammar._parsingSource, token_.StartPos, token_2.EndPos);
                }
                else
                {
                    if (this._grammar._parsingErrors._#_neg_ < pos)
                    {
                        this._grammar._parsingErrors._#_neg_ = pos;
                    }
                }
                return newPos2;
            }
            public _#prefix#__neg_(IGrammar grammar) : base('\0', '?')
            {
                this._grammar = (CalcParser.GrammarImpl)grammar;
            }
        }
        public class _#postfix#_mul_ : ExtensionPostfixBase<ExprAst>
        {
            private readonly CalcParser.GrammarImpl _grammar;
            public override RuleDescriptor Descriptor
            {
                get
                {
                    return CalcParser.GrammarImpl.GrammarDescriptorImpl._#postfix#_mul_.StaticDescriptor;
                }
            }
            public override int Parse(int startPos, int pos, string text, int[] bestOffsets, ref ExprAst result)
            {
                bool isBest = false;
                NToken token_2 = default(NToken);
                ExprAst token_3 = null;
                ExprAst prefixResult = result;
                ExprAst token_4 = prefixResult;
                bool _N_cache_9770 = pos >= 0;
                bool arg_AA_0;
                if (_N_cache_9770)
                {
                    if (true)
                    {
                        if (isBest)
                        {
                            arg_AA_0 = true;
                        }
                        else
                        {
                            isBest = (bestOffsets[0] < pos);
                            arg_AA_0 = (isBest || bestOffsets[0] == pos);
                        }
                        goto IL_9F;
                    }
                }
                arg_AA_0 = false;
                IL_9F:
                int arg_36F_0;
                if (arg_AA_0)
                {
                    int arg_108_0;
                    if (pos < text.Length)
                    {
                        char c = text[pos];
                        arg_108_0 = ((c != '*') ? -1 : (pos + 1));
                    }
                    else
                    {
                        arg_108_0 = -1;
                    }
                    int newPos = arg_108_0;
                    if (newPos >= 0)
                    {
                        token_2 = new NToken(pos, newPos);
                    }
                    int pos2 = newPos;
                    bool _N_cache_9771 = pos2 >= 0;
                    bool arg_197_0;
                    if (_N_cache_9771)
                    {
                        if (true)
                        {
                            if (isBest)
                            {
                                arg_197_0 = true;
                            }
                            else
                            {
                                isBest = (bestOffsets[1] < pos2);
                                arg_197_0 = (isBest || bestOffsets[1] == pos2);
                            }
                            goto IL_18C;
                        }
                    }
                    arg_197_0 = false;
                    IL_18C:
                    if (arg_197_0)
                    {
                        int ofs = pos2;
                        int pos3 = this._grammar._#_s_(pos2, text);
                        bool _N_cache_9772 = pos3 >= 0;
                        bool arg_224_0;
                        if (_N_cache_9772)
                        {
                            if (true)
                            {
                                if (isBest)
                                {
                                    arg_224_0 = true;
                                }
                                else
                                {
                                    isBest = (bestOffsets[2] < pos3);
                                    arg_224_0 = (isBest || bestOffsets[2] == pos3);
                                }
                                goto IL_219;
                            }
                        }
                        arg_224_0 = false;
                        IL_219:
                        if (arg_224_0)
                        {
                            int ofs2 = pos3;
                            int pos4 = this._grammar._#_expr_(pos3, text, 20, ref token_3);
                            bool _N_cache_9773 = pos4 >= 0;
                            bool arg_2B5_0;
                            if (_N_cache_9773)
                            {
                                if (true)
                                {
                                    if (isBest)
                                    {
                                        arg_2B5_0 = true;
                                    }
                                    else
                                    {
                                        isBest = (bestOffsets[3] < pos4);
                                        arg_2B5_0 = (isBest || bestOffsets[3] == pos4);
                                    }
                                    goto IL_2AA;
                                }
                            }
                            arg_2B5_0 = false;
                            IL_2AA:
                            if (arg_2B5_0)
                            {
                                int ofs3 = pos4;
                                if (isBest)
                                {
                                    bestOffsets[0] = pos;
                                    bestOffsets[1] = ofs;
                                    bestOffsets[2] = ofs2;
                                    bestOffsets[3] = ofs3;
                                    int i = 4;
                                    while (i < bestOffsets.Length && bestOffsets[i] >= 0)
                                    {
                                        bestOffsets[i] = -1;
                                        i++;
                                    }
                                    arg_36F_0 = pos4;
                                }
                                else
                                {
                                    arg_36F_0 = -1;
                                }
                            }
                            else
                            {
                                arg_36F_0 = -1;
                            }
                        }
                        else
                        {
                            arg_36F_0 = -1;
                        }
                    }
                    else
                    {
                        arg_36F_0 = -1;
                    }
                }
                else
                {
                    arg_36F_0 = -1;
                }
                int newPos2 = arg_36F_0;
                if (newPos2 > 0)
                {
                    result = new CalcParser.Expr.Mul(token_4, token_2, token_3);
                    result.Location = new Location(this._grammar._parsingSource, token_4.StartPos, token_3.EndPos);
                }
                else
                {
                    if (this._grammar._parsingErrors._#_mul_ < pos)
                    {
                        this._grammar._parsingErrors._#_mul_ = pos;
                    }
                }
                return newPos2;
            }
            public _#postfix#_mul_(IGrammar grammar) : base(20, '\0', '?')
            {
                this._grammar = (CalcParser.GrammarImpl)grammar;
            }
        }
        public class _#postfix#_mod_ : ExtensionPostfixBase<ExprAst>
        {
            private readonly CalcParser.GrammarImpl _grammar;
            public override RuleDescriptor Descriptor
            {
                get
                {
                    return CalcParser.GrammarImpl.GrammarDescriptorImpl._#postfix#_mod_.StaticDescriptor;
                }
            }
            public override int Parse(int startPos, int pos, string text, int[] bestOffsets, ref ExprAst result)
            {
                bool isBest = false;
                NToken token_2 = default(NToken);
                ExprAst token_3 = null;
                ExprAst prefixResult = result;
                ExprAst token_4 = prefixResult;
                bool _N_cache_9893 = pos >= 0;
                bool arg_AA_0;
                if (_N_cache_9893)
                {
                    if (true)
                    {
                        if (isBest)
                        {
                            arg_AA_0 = true;
                        }
                        else
                        {
                            isBest = (bestOffsets[0] < pos);
                            arg_AA_0 = (isBest || bestOffsets[0] == pos);
                        }
                        goto IL_9F;
                    }
                }
                arg_AA_0 = false;
                IL_9F:
                int arg_36F_0;
                if (arg_AA_0)
                {
                    int arg_108_0;
                    if (pos < text.Length)
                    {
                        char c = text[pos];
                        arg_108_0 = ((c != '%') ? -1 : (pos + 1));
                    }
                    else
                    {
                        arg_108_0 = -1;
                    }
                    int newPos = arg_108_0;
                    if (newPos >= 0)
                    {
                        token_2 = new NToken(pos, newPos);
                    }
                    int pos2 = newPos;
                    bool _N_cache_9894 = pos2 >= 0;
                    bool arg_197_0;
                    if (_N_cache_9894)
                    {
                        if (true)
                        {
                            if (isBest)
                            {
                                arg_197_0 = true;
                            }
                            else
                            {
                                isBest = (bestOffsets[1] < pos2);
                                arg_197_0 = (isBest || bestOffsets[1] == pos2);
                            }
                            goto IL_18C;
                        }
                    }
                    arg_197_0 = false;
                    IL_18C:
                    if (arg_197_0)
                    {
                        int ofs = pos2;
                        int pos3 = this._grammar._#_s_(pos2, text);
                        bool _N_cache_9895 = pos3 >= 0;
                        bool arg_224_0;
                        if (_N_cache_9895)
                        {
                            if (true)
                            {
                                if (isBest)
                                {
                                    arg_224_0 = true;
                                }
                                else
                                {
                                    isBest = (bestOffsets[2] < pos3);
                                    arg_224_0 = (isBest || bestOffsets[2] == pos3);
                                }
                                goto IL_219;
                            }
                        }
                        arg_224_0 = false;
                        IL_219:
                        if (arg_224_0)
                        {
                            int ofs2 = pos3;
                            int pos4 = this._grammar._#_expr_(pos3, text, 20, ref token_3);
                            bool _N_cache_9896 = pos4 >= 0;
                            bool arg_2B5_0;
                            if (_N_cache_9896)
                            {
                                if (true)
                                {
                                    if (isBest)
                                    {
                                        arg_2B5_0 = true;
                                    }
                                    else
                                    {
                                        isBest = (bestOffsets[3] < pos4);
                                        arg_2B5_0 = (isBest || bestOffsets[3] == pos4);
                                    }
                                    goto IL_2AA;
                                }
                            }
                            arg_2B5_0 = false;
                            IL_2AA:
                            if (arg_2B5_0)
                            {
                                int ofs3 = pos4;
                                if (isBest)
                                {
                                    bestOffsets[0] = pos;
                                    bestOffsets[1] = ofs;
                                    bestOffsets[2] = ofs2;
                                    bestOffsets[3] = ofs3;
                                    int i = 4;
                                    while (i < bestOffsets.Length && bestOffsets[i] >= 0)
                                    {
                                        bestOffsets[i] = -1;
                                        i++;
                                    }
                                    arg_36F_0 = pos4;
                                }
                                else
                                {
                                    arg_36F_0 = -1;
                                }
                            }
                            else
                            {
                                arg_36F_0 = -1;
                            }
                        }
                        else
                        {
                            arg_36F_0 = -1;
                        }
                    }
                    else
                    {
                        arg_36F_0 = -1;
                    }
                }
                else
                {
                    arg_36F_0 = -1;
                }
                int newPos2 = arg_36F_0;
                if (newPos2 > 0)
                {
                    result = new CalcParser.Expr.Mod(token_4, token_2, token_3);
                    result.Location = new Location(this._grammar._parsingSource, token_4.StartPos, token_3.EndPos);
                }
                else
                {
                    if (this._grammar._parsingErrors._#_mod_ < pos)
                    {
                        this._grammar._parsingErrors._#_mod_ = pos;
                    }
                }
                return newPos2;
            }
            public _#postfix#_mod_(IGrammar grammar) : base(20, '\0', '?')
            {
                this._grammar = (CalcParser.GrammarImpl)grammar;
            }
        }
        public class _#postfix#_div_ : ExtensionPostfixBase<ExprAst>
        {
            private readonly CalcParser.GrammarImpl _grammar;
            public override RuleDescriptor Descriptor
            {
                get
                {
                    return CalcParser.GrammarImpl.GrammarDescriptorImpl._#postfix#_div_.StaticDescriptor;
                }
            }
            public override int Parse(int startPos, int pos, string text, int[] bestOffsets, ref ExprAst result)
            {
                bool isBest = false;
                NToken token_2 = default(NToken);
                ExprAst token_3 = null;
                ExprAst prefixResult = result;
                ExprAst token_4 = prefixResult;
                bool _N_cache_10016 = pos >= 0;
                bool arg_AA_0;
                if (_N_cache_10016)
                {
                    if (true)
                    {
                        if (isBest)
                        {
                            arg_AA_0 = true;
                        }
                        else
                        {
                            isBest = (bestOffsets[0] < pos);
                            arg_AA_0 = (isBest || bestOffsets[0] == pos);
                        }
                        goto IL_9F;
                    }
                }
                arg_AA_0 = false;
                IL_9F:
                int arg_36F_0;
                if (arg_AA_0)
                {
                    int arg_108_0;
                    if (pos < text.Length)
                    {
                        char c = text[pos];
                        arg_108_0 = ((c != '/') ? -1 : (pos + 1));
                    }
                    else
                    {
                        arg_108_0 = -1;
                    }
                    int newPos = arg_108_0;
                    if (newPos >= 0)
                    {
                        token_2 = new NToken(pos, newPos);
                    }
                    int pos2 = newPos;
                    bool _N_cache_10017 = pos2 >= 0;
                    bool arg_197_0;
                    if (_N_cache_10017)
                    {
                        if (true)
                        {
                            if (isBest)
                            {
                                arg_197_0 = true;
                            }
                            else
                            {
                                isBest = (bestOffsets[1] < pos2);
                                arg_197_0 = (isBest || bestOffsets[1] == pos2);
                            }
                            goto IL_18C;
                        }
                    }
                    arg_197_0 = false;
                    IL_18C:
                    if (arg_197_0)
                    {
                        int ofs = pos2;
                        int pos3 = this._grammar._#_s_(pos2, text);
                        bool _N_cache_10018 = pos3 >= 0;
                        bool arg_224_0;
                        if (_N_cache_10018)
                        {
                            if (true)
                            {
                                if (isBest)
                                {
                                    arg_224_0 = true;
                                }
                                else
                                {
                                    isBest = (bestOffsets[2] < pos3);
                                    arg_224_0 = (isBest || bestOffsets[2] == pos3);
                                }
                                goto IL_219;
                            }
                        }
                        arg_224_0 = false;
                        IL_219:
                        if (arg_224_0)
                        {
                            int ofs2 = pos3;
                            int pos4 = this._grammar._#_expr_(pos3, text, 20, ref token_3);
                            bool _N_cache_10019 = pos4 >= 0;
                            bool arg_2B5_0;
                            if (_N_cache_10019)
                            {
                                if (true)
                                {
                                    if (isBest)
                                    {
                                        arg_2B5_0 = true;
                                    }
                                    else
                                    {
                                        isBest = (bestOffsets[3] < pos4);
                                        arg_2B5_0 = (isBest || bestOffsets[3] == pos4);
                                    }
                                    goto IL_2AA;
                                }
                            }
                            arg_2B5_0 = false;
                            IL_2AA:
                            if (arg_2B5_0)
                            {
                                int ofs3 = pos4;
                                if (isBest)
                                {
                                    bestOffsets[0] = pos;
                                    bestOffsets[1] = ofs;
                                    bestOffsets[2] = ofs2;
                                    bestOffsets[3] = ofs3;
                                    int i = 4;
                                    while (i < bestOffsets.Length && bestOffsets[i] >= 0)
                                    {
                                        bestOffsets[i] = -1;
                                        i++;
                                    }
                                    arg_36F_0 = pos4;
                                }
                                else
                                {
                                    arg_36F_0 = -1;
                                }
                            }
                            else
                            {
                                arg_36F_0 = -1;
                            }
                        }
                        else
                        {
                            arg_36F_0 = -1;
                        }
                    }
                    else
                    {
                        arg_36F_0 = -1;
                    }
                }
                else
                {
                    arg_36F_0 = -1;
                }
                int newPos2 = arg_36F_0;
                if (newPos2 > 0)
                {
                    result = new CalcParser.Expr.Div(token_4, token_2, token_3);
                    result.Location = new Location(this._grammar._parsingSource, token_4.StartPos, token_3.EndPos);
                }
                else
                {
                    if (this._grammar._parsingErrors._#_div_ < pos)
                    {
                        this._grammar._parsingErrors._#_div_ = pos;
                    }
                }
                return newPos2;
            }
            public _#postfix#_div_(IGrammar grammar) : base(20, '\0', '?')
            {
                this._grammar = (CalcParser.GrammarImpl)grammar;
            }
        }
        public class _#postfix#_add_ : ExtensionPostfixBase<ExprAst>
        {
            private readonly CalcParser.GrammarImpl _grammar;
            public override RuleDescriptor Descriptor
            {
                get
                {
                    return CalcParser.GrammarImpl.GrammarDescriptorImpl._#postfix#_add_.StaticDescriptor;
                }
            }
            public override int Parse(int startPos, int pos, string text, int[] bestOffsets, ref ExprAst result)
            {
                bool isBest = false;
                NToken token_2 = default(NToken);
                ExprAst token_3 = null;
                ExprAst prefixResult = result;
                ExprAst token_4 = prefixResult;
                bool _N_cache_10139 = pos >= 0;
                bool arg_AA_0;
                if (_N_cache_10139)
                {
                    if (true)
                    {
                        if (isBest)
                        {
                            arg_AA_0 = true;
                        }
                        else
                        {
                            isBest = (bestOffsets[0] < pos);
                            arg_AA_0 = (isBest || bestOffsets[0] == pos);
                        }
                        goto IL_9F;
                    }
                }
                arg_AA_0 = false;
                IL_9F:
                int arg_36F_0;
                if (arg_AA_0)
                {
                    int arg_108_0;
                    if (pos < text.Length)
                    {
                        char c = text[pos];
                        arg_108_0 = ((c != '+') ? -1 : (pos + 1));
                    }
                    else
                    {
                        arg_108_0 = -1;
                    }
                    int newPos = arg_108_0;
                    if (newPos >= 0)
                    {
                        token_2 = new NToken(pos, newPos);
                    }
                    int pos2 = newPos;
                    bool _N_cache_10140 = pos2 >= 0;
                    bool arg_197_0;
                    if (_N_cache_10140)
                    {
                        if (true)
                        {
                            if (isBest)
                            {
                                arg_197_0 = true;
                            }
                            else
                            {
                                isBest = (bestOffsets[1] < pos2);
                                arg_197_0 = (isBest || bestOffsets[1] == pos2);
                            }
                            goto IL_18C;
                        }
                    }
                    arg_197_0 = false;
                    IL_18C:
                    if (arg_197_0)
                    {
                        int ofs = pos2;
                        int pos3 = this._grammar._#_s_(pos2, text);
                        bool _N_cache_10141 = pos3 >= 0;
                        bool arg_224_0;
                        if (_N_cache_10141)
                        {
                            if (true)
                            {
                                if (isBest)
                                {
                                    arg_224_0 = true;
                                }
                                else
                                {
                                    isBest = (bestOffsets[2] < pos3);
                                    arg_224_0 = (isBest || bestOffsets[2] == pos3);
                                }
                                goto IL_219;
                            }
                        }
                        arg_224_0 = false;
                        IL_219:
                        if (arg_224_0)
                        {
                            int ofs2 = pos3;
                            int pos4 = this._grammar._#_expr_(pos3, text, 10, ref token_3);
                            bool _N_cache_10142 = pos4 >= 0;
                            bool arg_2B5_0;
                            if (_N_cache_10142)
                            {
                                if (true)
                                {
                                    if (isBest)
                                    {
                                        arg_2B5_0 = true;
                                    }
                                    else
                                    {
                                        isBest = (bestOffsets[3] < pos4);
                                        arg_2B5_0 = (isBest || bestOffsets[3] == pos4);
                                    }
                                    goto IL_2AA;
                                }
                            }
                            arg_2B5_0 = false;
                            IL_2AA:
                            if (arg_2B5_0)
                            {
                                int ofs3 = pos4;
                                if (isBest)
                                {
                                    bestOffsets[0] = pos;
                                    bestOffsets[1] = ofs;
                                    bestOffsets[2] = ofs2;
                                    bestOffsets[3] = ofs3;
                                    int i = 4;
                                    while (i < bestOffsets.Length && bestOffsets[i] >= 0)
                                    {
                                        bestOffsets[i] = -1;
                                        i++;
                                    }
                                    arg_36F_0 = pos4;
                                }
                                else
                                {
                                    arg_36F_0 = -1;
                                }
                            }
                            else
                            {
                                arg_36F_0 = -1;
                            }
                        }
                        else
                        {
                            arg_36F_0 = -1;
                        }
                    }
                    else
                    {
                        arg_36F_0 = -1;
                    }
                }
                else
                {
                    arg_36F_0 = -1;
                }
                int newPos2 = arg_36F_0;
                if (newPos2 > 0)
                {
                    result = new CalcParser.Expr.Add(token_4, token_2, token_3);
                    result.Location = new Location(this._grammar._parsingSource, token_4.StartPos, token_3.EndPos);
                }
                else
                {
                    if (this._grammar._parsingErrors._#_add_ < pos)
                    {
                        this._grammar._parsingErrors._#_add_ = pos;
                    }
                }
                return newPos2;
            }
            public _#postfix#_add_(IGrammar grammar) : base(10, '\0', '?')
            {
                this._grammar = (CalcParser.GrammarImpl)grammar;
            }
        }
        private IncParser.GrammarImpl _#grammar#0;
        private NumParser.GrammarImpl _#grammar#1;
        public ExtensionPostfixBase<ExprAst>[] _#_expr_PostfixRules_ = new ExtensionPostfixBase<ExprAst>[0];
        public ExtensionPrefixBase<ExprAst>[] _#_expr_PrefixRules__ = new ExtensionPrefixBase<ExprAst>[0];
        private int _#_expr_PrefixEndPos_ = -1;
        private ExprAst _#_expr_PrefixResult_;
        private int _#_expr_EndPos_______ = -1;
        private ExprAst _#_expr_Result_______;
        private int _#_expr_BindingPower_ = -1;
        private int _#_expr_StartPos_____ = -1;
        private int _#_start_EndPos______ = -1;
        private ExprAst _#_start_Result______;
        private int _#_start_StartPos____ = -1;
        [CompilerGenerated, DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private Parser _N_Parser_4066;
        private CalcParser.GrammarImpl.ParsingErrorsImpl _parsingErrors;
        private static readonly GrammarDescriptor _descriptor;
        public override Parser Parser
        {
            get;
            private set;
        }
        public static GrammarDescriptor StaticDescriptor
        {
            get
            {
                return CalcParser.GrammarImpl._descriptor;
            }
        }
        public GrammarDescriptor Descriptor
        {
            get
            {
                return CalcParser.GrammarImpl._descriptor;
            }
        }
        public new SourceSnapshot get_ParsingSource()
        {
            return base.ParsingSource;
        }
        public void Init()
        {
            this._parsingSource = this.Parser.ParsingSource;
            this._parsingErrors = (CalcParser.GrammarImpl.ParsingErrorsImpl)this.Parser.GetParsingErrorsForGrammar(CalcParser.GrammarImpl.StaticDescriptor);
            this._#grammar#1 = (NumParser.GrammarImpl)this.Parser.GetGrammar(NumParser.GrammarImpl.StaticDescriptor).Value;
            this._#grammar#0 = (IncParser.GrammarImpl)this.Parser.GetGrammar(IncParser.GrammarImpl.StaticDescriptor).Value;
            this.LoadExtensionRules();
        }
        public IGrammarState SaveState()
        {
            return new CalcParser.GrammarImpl.GrammarStateImpl(this);
        }
        private void LoadExtensionRules()
        {
            checked
            {
                ExtensionPrefixBase<ExprAst>[] e = this._#_expr_PrefixRules__;
                int result = 0;
                if (e != null)
                {
                    result = e.Length;
                }
                int prevLength = result;
                Array.Resize<ExtensionPrefixBase<ExprAst>>(ref this._#_expr_PrefixRules__, prevLength + 5);
                this._#_expr_PrefixRules__[prevLength + 0] = new CalcParser.GrammarImpl._#prefix#__neg_(this);
                this._#_expr_PrefixRules__[prevLength + 1] = new CalcParser.GrammarImpl._#prefix#__num_(this);
                this._#_expr_PrefixRules__[prevLength + 2] = new CalcParser.GrammarImpl._#prefix#__prefixDec_(this);
                this._#_expr_PrefixRules__[prevLength + 3] = new CalcParser.GrammarImpl._#prefix#__rounds_(this);
                this._#_expr_PrefixRules__[prevLength + 4] = new CalcParser.GrammarImpl._#prefix#__seq_(this);
                ExtensionPostfixBase<ExprAst>[] e2 = this._#_expr_PostfixRules_;
                int result2 = 0;
                if (e2 != null)
                {
                    result2 = e2.Length;
                }
                prevLength = result2;
                Array.Resize<ExtensionPostfixBase<ExprAst>>(ref this._#_expr_PostfixRules_, prevLength + 7);
                this._#_expr_PostfixRules_[prevLength + 0] = new CalcParser.GrammarImpl._#postfix#_add_(this);
                this._#_expr_PostfixRules_[prevLength + 1] = new CalcParser.GrammarImpl._#postfix#_div_(this);
                this._#_expr_PostfixRules_[prevLength + 2] = new CalcParser.GrammarImpl._#postfix#_mod_(this);
                this._#_expr_PostfixRules_[prevLength + 3] = new CalcParser.GrammarImpl._#postfix#_mul_(this);
                this._#_expr_PostfixRules_[prevLength + 4] = new CalcParser.GrammarImpl._#postfix#_postfixDec_(this);
                this._#_expr_PostfixRules_[prevLength + 5] = new CalcParser.GrammarImpl._#postfix#_pow_(this);
                this._#_expr_PostfixRules_[prevLength + 6] = new CalcParser.GrammarImpl._#postfix#_sub_(this);
            }
        }
        private void ResetMemoization()
        {
            this._#_start_StartPos____ = -1;
            this._#_start_Result______ = null;
            this._#_start_EndPos______ = -1;
            this._#_expr_StartPos_____ = -1;
            this._#_expr_BindingPower_ = -1;
            this._#_expr_Result_______ = null;
            this._#_expr_EndPos_______ = -1;
            this._#_expr_PrefixResult_ = null;
            this._#_expr_PrefixEndPos_ = -1;
        }
        public int _#_expr_(int pos, string text, int bindingPower)
        {
            ExprAst result = null;
            return this._#_expr_(pos, text, bindingPower, ref result);
        }
        public int _#_expr_(int pos, string text, int bindingPower, ref ExprAst curResult)
        {
            int _N_return = 0;
            int[] bestOffsets = new int[32];
            int curEndPos = -1;
            ExprAst newResult = null;
            if (this._#_expr_StartPos_____ == pos)
            {
                if (this._#_expr_EndPos_______ < 0)
                {
                    _N_return = -1;
                    return _N_return;
                }
                if (this._#_expr_BindingPower_ == bindingPower)
                {
                    curResult = this._#_expr_Result_______;
                    _N_return = this._#_expr_EndPos_______;
                    return _N_return;
                }
                this._#_expr_BindingPower_ = bindingPower;
                this._#_expr_EndPos_______ = -1;
                curResult = this._#_expr_PrefixResult_;
                curEndPos = this._#_expr_PrefixEndPos_;
            }
            else
            {
                this._#_expr_BindingPower_ = bindingPower;
                this._#_expr_StartPos_____ = pos;
                this._#_expr_PrefixEndPos_ = -1;
                this._#_expr_EndPos_______ = -1;
                int i = 0;
                while (i < bestOffsets.Length && bestOffsets[i] >= 0)
                {
                    bestOffsets[i] = -1;
                    i++;
                }
                if (pos < text.Length)
                {
                    char c = text[pos];
                    ExtensionPrefixBase<ExprAst>[] #_expr_PrefixRules__ = this._#_expr_PrefixRules__;
                    for (int k = 0; k < #_expr_PrefixRules__.Length; k++)
                    {
                        ExtensionPrefixBase<ExprAst> extensionPrefixBase = #_expr_PrefixRules__[k];
                        ExtensionPrefixBase<ExprAst> prefixRule = (ExtensionPrefixBase<ExprAst>)extensionPrefixBase;
                        if (prefixRule.LowerBound <= c && c <= prefixRule.UpperBound)
                        {
                            int newEndPos = prefixRule.Parse(pos, text, bestOffsets, ref newResult);
                            if (newEndPos > 0)
                            {
                                curResult = newResult;
                                curEndPos = newEndPos;
                            }
                        }
                    }
                }
                else
                {
                    ExtensionPrefixBase<ExprAst>[] #_expr_PrefixRules__2 = this._#_expr_PrefixRules__;
                    for (int l = 0; l < #_expr_PrefixRules__2.Length; l++)
                    {
                        ExtensionPrefixBase<ExprAst> extensionPrefixBase2 = #_expr_PrefixRules__2[l];
                        ExtensionPrefixBase<ExprAst> prefixRule2 = (ExtensionPrefixBase<ExprAst>)extensionPrefixBase2;
                        int newEndPos = prefixRule2.Parse(pos, text, bestOffsets, ref newResult);
                        if (newEndPos > 0)
                        {
                            curResult = newResult;
                            curEndPos = newEndPos;
                        }
                    }
                }
            }
            if (curEndPos >= 0)
            {
                ExprAst prefixResult = curResult;
                int prefixEndPos = curEndPos;
                ExprAst bestResult = curResult;
                int bestEndPos = curEndPos;
                while (curEndPos < text.Length)
                {
                    int j = 0;
                    while (j < bestOffsets.Length && bestOffsets[j] >= 0)
                    {
                        bestOffsets[j] = -1;
                        j++;
                    }
                    char c = text[curEndPos];
                    ExtensionPostfixBase<ExprAst>[] #_expr_PostfixRules_ = this._#_expr_PostfixRules_;
                    for (int m = 0; m < #_expr_PostfixRules_.Length; m++)
                    {
                        ExtensionPostfixBase<ExprAst> extensionPostfixBase = #_expr_PostfixRules_[m];
                        ExtensionPostfixBase<ExprAst> postfixRule = (ExtensionPostfixBase<ExprAst>)extensionPostfixBase;
                        if (postfixRule.LowerBound <= c && c <= postfixRule.UpperBound && bindingPower < postfixRule.BindingPower)
                        {
                            newResult = curResult;
                            int newEndPos = postfixRule.Parse(pos, curEndPos, text, bestOffsets, ref newResult);
                            if (newEndPos > 0)
                            {
                                bestEndPos = newEndPos;
                                bestResult = newResult;
                            }
                        }
                    }
                    if (bestEndPos == curEndPos)
                    {
                        IL_3A8:
                        this._#_expr_BindingPower_ = bindingPower;
                        this._#_expr_StartPos_____ = pos;
                        this._#_expr_PrefixResult_ = prefixResult;
                        this._#_expr_PrefixEndPos_ = prefixEndPos;
                        this._#_expr_Result_______ = curResult;
                        this._#_expr_EndPos_______ = curEndPos;
                        _N_return = curEndPos;
                        return _N_return;
                    }
                    curResult = bestResult;
                    curEndPos = bestEndPos;
                }
                goto IL_3A8;
            }
            _N_return = -1;
            return _N_return;
        }
        public int _#_any_(int pos, string text)
        {
            return (pos >= text.Length) ? -1 : (pos + 1);
        }
        public int _#_start_(int pos, string text, ref ExprAst result)
        {
            ExprAst token_ = null;
            int arg_1BA_0;
            if (this._#_start_StartPos____ == pos)
            {
                if (this._#_start_EndPos______ >= 0)
                {
                    result = this._#_start_Result______;
                }
                arg_1BA_0 = this._#_start_EndPos______;
            }
            else
            {
                int pos2 = this._#_s_(pos, text);
                int arg_12C_0;
                if (pos2 >= 0)
                {
                    int pos3 = this._#_expr_(pos2, text, 0, ref token_);
                    if (pos3 >= 0)
                    {
                        int newPos = this._#_any_(pos3, text);
                        int pos4 = (newPos >= 0) ? -1 : pos3;
                        arg_12C_0 = ((pos4 < 0) ? -1 : pos4);
                    }
                    else
                    {
                        arg_12C_0 = -1;
                    }
                }
                else
                {
                    arg_12C_0 = -1;
                }
                int newPos2 = arg_12C_0;
                this._#_start_StartPos____ = pos;
                this._#_start_EndPos______ = newPos2;
                if (newPos2 >= 0)
                {
                    result = token_;
                    result.Location = new Location(this._parsingSource, token_.StartPos, token_.EndPos);
                    this._#_start_Result______ = result;
                }
                else
                {
                    if (this._parsingErrors._#_start_ < pos)
                    {
                        this._parsingErrors._#_start_ = pos;
                    }
                }
                arg_1BA_0 = newPos2;
            }
            return arg_1BA_0;
        }
        public int _#_s_(int pos, string text)
        {
            int num = pos;
            while (true)
            {
                int arg_6A_0;
                if (num < text.Length)
                {
                    char c = text[num];
                    arg_6A_0 = ((c != ' ') ? -1 : (num + 1));
                }
                else
                {
                    arg_6A_0 = -1;
                }
                int newPos = arg_6A_0;
                if (newPos < 0)
                {
                    break;
                }
                num = newPos;
            }
            return num;
        }
        static GrammarImpl()
        {
            CalcParser.GrammarImpl._descriptor = new CalcParser.GrammarImpl.GrammarDescriptorImpl();
        }
        public GrammarImpl()
        {
        }
        public GrammarImpl(Parser parser)
        {
            if (parser == null)
            {
                throw new ArgumentNullException("parser", "The ``NotNull'' contract of parameter ``parser'' has been violated. See Main.n:17:2:49:2: .");
            }
            this.Parser = parser;
        }
        public override Nemerle.Builtins.Tuple<int, ExprAst> TryParseExpr(SourceSnapshot source)
        {
            checked
            {
                if (source == null)
                {
                    throw new ArgumentNullException("source", "The ``NotNull'' contract of parameter ``source'' has been violated. See Main.n:17:2:49:2: .");
                }
                this.ResetMemoization();
                this.Parser = new Parser(this, source);
                GrammarDescriptor[] dependencies = this.Descriptor.Dependencies;
                for (int i = 0; i < dependencies.Length; i++)
                {
                    GrammarDescriptor grammarDescriptor = dependencies[i];
                    GrammarDescriptor descriptor = grammarDescriptor;
                    this.Parser.AddGrammar(descriptor);
                }
                this.Init();
                ExprAst result = null;
                int pos = this._#_expr_(0, this._parsingSource.Text, 0, ref result);
                return new Nemerle.Builtins.Tuple<int, ExprAst>(pos, result);
            }
        }
        public override Nemerle.Builtins.Tuple<int, ExprAst> TryParseStart(SourceSnapshot source)
        {
            checked
            {
                if (source == null)
                {
                    throw new ArgumentNullException("source", "The ``NotNull'' contract of parameter ``source'' has been violated. See Main.n:17:2:49:2: .");
                }
                this.ResetMemoization();
                this.Parser = new Parser(this, source);
                GrammarDescriptor[] dependencies = this.Descriptor.Dependencies;
                for (int i = 0; i < dependencies.Length; i++)
                {
                    GrammarDescriptor grammarDescriptor = dependencies[i];
                    GrammarDescriptor descriptor = grammarDescriptor;
                    this.Parser.AddGrammar(descriptor);
                }
                this.Init();
                ExprAst result = null;
                int pos = this._#_start_(0, this._parsingSource.Text, ref result);
                return new Nemerle.Builtins.Tuple<int, ExprAst>(pos, result);
            }
        }
    }
    [Variant("CalcParser.Expr.Sub,CalcParser.Expr.Seq,CalcParser.Expr.Rounds,CalcParser.Expr.PrefixDec,CalcParser.Expr.Pow,CalcParser.Expr.PostfixDec,CalcParser.Expr.Num,CalcParser.Expr.Neg,CalcParser.Expr.Mul,CalcParser.Expr.Mod,CalcParser.Expr.Div,CalcParser.Expr.Add")]
    public abstract class Expr : ExprAst
    {
        [VariantOption]
        public class Add : CalcParser.Expr
        {
            public readonly ExprAst l;
            public readonly NToken op;
            public readonly ExprAst r;
            public override int _N_GetVariantCode()
            {
                return 0;
            }
            public Add()
            {
            }
            public Add(ExprAst l, NToken op, ExprAst r)
            {
                this.l = l;
                this.op = op;
                this.r = r;
            }
        }
        [VariantOption]
        public class Div : CalcParser.Expr
        {
            public readonly ExprAst l;
            public readonly NToken op;
            public readonly ExprAst r;
            public override int _N_GetVariantCode()
            {
                return 1;
            }
            public Div()
            {
            }
            public Div(ExprAst l, NToken op, ExprAst r)
            {
                this.l = l;
                this.op = op;
                this.r = r;
            }
        }
        [VariantOption]
        public class Mod : CalcParser.Expr
        {
            public readonly ExprAst l;
            public readonly NToken op;
            public readonly ExprAst r;
            public override int _N_GetVariantCode()
            {
                return 2;
            }
            public Mod()
            {
            }
            public Mod(ExprAst l, NToken op, ExprAst r)
            {
                this.l = l;
                this.op = op;
                this.r = r;
            }
        }
        [VariantOption]
        public class Mul : CalcParser.Expr
        {
            public readonly ExprAst l;
            public readonly NToken op;
            public readonly ExprAst r;
            public override int _N_GetVariantCode()
            {
                return 3;
            }
            public Mul()
            {
            }
            public Mul(ExprAst l, NToken op, ExprAst r)
            {
                this.l = l;
                this.op = op;
                this.r = r;
            }
        }
        [VariantOption]
        public class Neg : CalcParser.Expr
        {
            public readonly NToken op;
            public readonly ExprAst expr;
            public override int _N_GetVariantCode()
            {
                return 4;
            }
            public Neg()
            {
            }
            public Neg(NToken op, ExprAst expr)
            {
                this.op = op;
                this.expr = expr;
            }
        }
        [VariantOption]
        public class Num : CalcParser.Expr
        {
            public readonly string num;
            public override int _N_GetVariantCode()
            {
                return 5;
            }
            public Num()
            {
            }
            public Num(string num)
            {
                this.num = num;
            }
        }
        [VariantOption]
        public class PostfixDec : CalcParser.Expr
        {
            public readonly ExprAst expr;
            public readonly NToken op;
            public override int _N_GetVariantCode()
            {
                return 6;
            }
            public PostfixDec()
            {
            }
            public PostfixDec(ExprAst expr, NToken op)
            {
                this.expr = expr;
                this.op = op;
            }
        }
        [VariantOption]
        public class Pow : CalcParser.Expr
        {
            public readonly ExprAst l;
            public readonly NToken op;
            public readonly ExprAst r;
            public override int _N_GetVariantCode()
            {
                return 7;
            }
            public Pow()
            {
            }
            public Pow(ExprAst l, NToken op, ExprAst r)
            {
                this.l = l;
                this.op = op;
                this.r = r;
            }
        }
        [VariantOption]
        public class PrefixDec : CalcParser.Expr
        {
            public readonly NToken op;
            public readonly ExprAst expr;
            public override int _N_GetVariantCode()
            {
                return 8;
            }
            public PrefixDec()
            {
            }
            public PrefixDec(NToken op, ExprAst expr)
            {
                this.op = op;
                this.expr = expr;
            }
        }
        [VariantOption]
        public class Rounds : CalcParser.Expr
        {
            public readonly NToken l;
            public readonly ExprAst expr;
            public readonly NToken r;
            public override int _N_GetVariantCode()
            {
                return 9;
            }
            public Rounds()
            {
            }
            public Rounds(NToken l, ExprAst expr, NToken r)
            {
                this.l = l;
                this.expr = expr;
                this.r = r;
            }
        }
        [VariantOption]
        public class Seq : CalcParser.Expr
        {
            public readonly NToken l;
            public readonly list<ExprAst> expr;
            public readonly NToken r;
            public override int _N_GetVariantCode()
            {
                return 10;
            }
            public Seq()
            {
            }
            public Seq(NToken l, list<ExprAst> expr, NToken r)
            {
                this.l = l;
                this.expr = expr;
                this.r = r;
            }
        }
        [VariantOption]
        public class Sub : CalcParser.Expr
        {
            public readonly ExprAst l;
            public readonly NToken op;
            public readonly ExprAst r;
            public override int _N_GetVariantCode()
            {
                return 11;
            }
            public Sub()
            {
            }
            public Sub(ExprAst l, NToken op, ExprAst r)
            {
                this.l = l;
                this.op = op;
                this.r = r;
            }
        }
        public abstract override int _N_GetVariantCode();
        public static int _N_GetVariantCodeSafe(CalcParser.Expr x)
        {
            return ((object)x != null) ? x._N_GetVariantCode() : -1;
        }
        public static int _N_GetVariantCodeObject(object x)
        {
            int arg_1E_0;
            if (x is CalcParser.Expr)
            {
                CalcParser.Expr expr = (CalcParser.Expr)x;
                arg_1E_0 = expr._N_GetVariantCode();
            }
            else
            {
                arg_1E_0 = -1;
            }
            return arg_1E_0;
        }
    }
    private SourceSnapshot _parsingSource;
    public abstract override Parser Parser
    {
        get;
    }
    public SourceSnapshot ParsingSource
    {
        get
        {
            return this._parsingSource;
        }
    }
    public string GetText(NToken tok)
    {
        return this._parsingSource.OriginalText.Substring(tok.StartPos, checked(tok.EndPos - tok.StartPos));
    }
    public Location GetLocation(NToken tok)
    {
        return new Location(this._parsingSource, tok.StartPos, tok.EndPos);
    }
    public option<ExprAst> ParseExpr(string text)
    {
        Nemerle.Builtins.Tuple<int, ExprAst> _N_cache_5180 = this.TryParseExpr(text);
        int pos = _N_cache_5180.Field0;
        ExprAst res = _N_cache_5180.Field1;
        return (pos >= 0) ? new option<ExprAst>.Some(res) : option<ExprAst>.None._N_constant_object;
    }
    public option<ExprAst> ParseExpr(SourceSnapshot source)
    {
        Nemerle.Builtins.Tuple<int, ExprAst> _N_cache_5193 = this.TryParseExpr(source);
        int pos = _N_cache_5193.Field0;
        ExprAst res = _N_cache_5193.Field1;
        return (pos >= 0) ? new option<ExprAst>.Some(res) : option<ExprAst>.None._N_constant_object;
    }
    public Nemerle.Builtins.Tuple<int, ExprAst> TryParseExpr(string text)
    {
        return this.TryParseExpr(new SourceSnapshot(text, 0, ""));
    }
    public abstract override Nemerle.Builtins.Tuple<int, ExprAst> TryParseExpr(SourceSnapshot source);
    public option<ExprAst> ParseStart(string text)
    {
        Nemerle.Builtins.Tuple<int, ExprAst> _N_cache_5210 = this.TryParseStart(text);
        int pos = _N_cache_5210.Field0;
        ExprAst res = _N_cache_5210.Field1;
        return (pos >= 0) ? new option<ExprAst>.Some(res) : option<ExprAst>.None._N_constant_object;
    }
    public option<ExprAst> ParseStart(SourceSnapshot source)
    {
        Nemerle.Builtins.Tuple<int, ExprAst> _N_cache_5223 = this.TryParseStart(source);
        int pos = _N_cache_5223.Field0;
        ExprAst res = _N_cache_5223.Field1;
        return (pos >= 0) ? new option<ExprAst>.Some(res) : option<ExprAst>.None._N_constant_object;
    }
    public Nemerle.Builtins.Tuple<int, ExprAst> TryParseStart(string text)
    {
        return this.TryParseStart(new SourceSnapshot(text, 0, ""));
    }
    public abstract override Nemerle.Builtins.Tuple<int, ExprAst> TryParseStart(SourceSnapshot source);
}


ME>без тормозов -- надо подумать, но сейчас лень

ME>с чуть худшим синтаксисом -- перетащив его в треугольные скобки -- без тормозов
Кода у тебя будет минимум раз в 5 больше. И только для базового функционала.
Как на шаблонах делать восстановление после ошибок я вообще не представляю.
ЗЫ Я сам мастер шаблонов.
Автор: WolfHound
Дата: 06.02.12

Так что знаю о чем гворю.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[16]: Тюринг-полные ли шаблоны C++?
От: WolfHound  
Дата: 10.02.12 10:00
Оценка:
Здравствуйте, m e, Вы писали:

ME>насчет модели (в прошлом посте) -- скажем по 2-3 строчки про остальные 10 не столь распостраненных способов

ME>(+ примерчик), и мне уже че-то будет ясно

ME>или такой текст уже есть? тогда ссылку

http://rsdn.ru/summary/3766.xml
Смотри "Макросы Nemerle – расширенный курс" в 4х частях.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[13]: Тюринг-полные ли шаблоны C++?
От: VladD2 Российская Империя www.nemerle.org
Дата: 10.02.12 12:40
Оценка:
Здравствуйте, WolfHound, Вы писали:

ME>>ладно, я предлагаю компромисс: я соглашаюсь на "сферическое в вакууме" и не доказываю, что оно нужно, а вы с владом рассказываете, *что* приводит к трудностям реализовать это на немерле

WH>Реализовать можно. Но будет много букв.

Да не будет много букв. Просто нужна конкретная постановка задачи.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[16]: Тюринг-полные ли шаблоны C++?
От: VladD2 Российская Империя www.nemerle.org
Дата: 10.02.12 13:45
Оценка:
Здравствуйте, m e, Вы писали:

WH>>Ты попробуй найти класс по имени и туда что-то добавить.

WH>>Не можешь?

ME>навскидку не помню, можно ли перегрузить оператор -> снаружи класса


Что-то связи не улавливаю.

>> Макросы Record, StructuralEquality, StructuralHashCode сразу получают TypeBuilder NToken'а. После чего достают из него поля. И генерируют на их основе нужные методы.


ME>1. тут идет дописывание, а не постройка с 0


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

С нуля это тоже пожалуйста. Это даже проще, чем дописывать.

ME>2. про это я уже писал -- шаблоны, несмотря на тьюринг-полноту, просто не могут получить нужные данные


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

WH>>Ну попробуй на плюсах повторить вот это: https://github.com/rampelstinskin/ParserGenerator


ME>"это" это https://github.com/rampelstinskin/ParserGenerator/blob/master/Test/Main.n ?


ME>ты давай опять словами, а то идея по коду не полностью восстанавливается

ME>то, что я восстановил -- с точностью до тормозов лишнего виртуального вызова функции -- без проблем
ME>без тормозов -- надо подумать, но сейчас лень

Я плякаль (с). Ты бы лучше попробовал разобраться, прежде чем нести такую фееричную фигню.
В общем, у меня складывается впечатление, что ты пришел просто потроллить.

Перенести на С++ его практически невозможно. Как минимум не выйдет сформировать человеческие сообщения об ошибках. Да и сгенерировать кучу сложных преобразований и оптимизаций на С++ будет практически нереально.

Если ты сравниваешь этот парсер со Спиритомт, то я тебя разочарую. Спирит — это детсадовская поделка. И я не преувеличиваю. Основные фишки этого генератора:
1. Динамическая расширяемость грамматик. Вот пример динамической загрузки расширяющих грамматик:
Основной парсер.
Расширяющий парсер.
Вот здесь, в правиле обработчике директивы using, происходит подгрузка грамматики из внешней сборки. Сами сборки грузятся в статическом конструкторе (выше).

2. Полная декларативность. Генератор генерирует не только код распознавателя, но и AST. Делается это заданием атрибута Ast() содержащего имена полей для новой ветки AST. При этом, естественно, проверяется их количество и количество подправил. Если что выдается осмоленные сообщение об ошибке. Если тип описывающий AST уже описан пользователем с модификатором partial, то типы сливаются. Так к сгенерированному AST можно добавить рукописные члены.

3. Поддержка левой рекурсии.

4. Поддержка разбора операторных грамматик с приоритетом и ассоциативностью задаваемых в виде силы связывания для выражений.

5. Внятные сообщения об ошибках позволяющие не только искать ошибки, но и подсказывать пользователю действия которые нужно осуществить (например, какую сигнатуру должен иметь обработчик для правила).

В отличии от Спирита данный генератор парсеров позволяет создавать парсеры для реальных языков прогкраммирования (а не только для мелких игрушек).

Что касается скорости парсинга, то мы надеемся она будет очень высокой. Причем сравнивать мы будем не с другими генераторами парсеров, а с рукописными парсерами обычно применяемыми сейчас на практике для разбора сложных языков. Прошлая версия нашего генератора порождала код который был быстрее чем многие качественные рукописные парсеры. Эта должна быть не хуже. Сейчас в ней еще не сделаны все запланированные оптимизации. Но даже сейчас их список не мал. Тут и переписывание в ДКА, и мемоизация результата разбора правил с целью исключения экспоненциального роста повторов разбора правил и многое другое.

ME>с чуть худшим синтаксисом -- перетащив его в треугольные скобки -- без тормозов


С чуть худшим? Это не то ли убожество что Спиритом завется является "чуть худшим синтаксисом"?

Без тормозов?!
http://habrahabr.ru/blogs/cpp/81175/

Код на Spirit медленно компилируется. Действительно медленно. Ни gcc, ни cl (Visual Studio 2008) не справились с компиляцией полной грамматики С++, состоящей из 180 правил, выпав с “out of heap”.


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

Если бы Вольфхаунд считал бы, что аналог его парсера можно было бы сделать на С++, то зачем бы ему вообще было связываться с Немерлом?

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

Кстати, как показывает практика, именно из С++-ников получаются отличные немерлисты . Так что если ты пришел разобраться, то милость просим в наше братство. Мы тебе поможем и ты сможешь по достоинству оценить технологию.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[16]: Тюринг-полные ли шаблоны C++?
От: VladD2 Российская Империя www.nemerle.org
Дата: 10.02.12 14:28
Оценка:
Здравствуйте, m e, Вы писали:

ME>более фундаментальная и полезная вещь -- это добавление в "рядом лежащий" класс, примерно как у тебя в примере StructuralEquality; но при этом надо уметь *читать* другие классы просто по имени


Ты мыслишь со свей колокольни. Как тебе уже неоднократно сказали, если у тебя есть полное имя класса, то получить по нему TypeBuilder, через который можно как угодно изменять тип не проблема. Делается это элементарно typer.BindType(имя_типа). Далее дело техники.

Вопрос в том зачем нужно искать что-то по имени?

Лучше описал бы реальную проблему (задачу), а не твои потуги ее решить в убогом С++. Мы бы тебе не просто подсказали, а показали бы реальное решение.

ME>читать вдалеке куда важнее, чем писать вдалеке; вообще даже писать вдалеке -- это хулиганство какое-то (за некоторыми исключениями)


В Н нет разницы читать или писать. Весь доступ к информации о типах делается через класс TypeInfo. Класс TypeBuilder является его наследником и дополняет его методами позволяющими добавлять и изменять тип. При этом нет разницы в каких файлах и в скольких файлах лежат реальные типы. Ограничение только одно — изменяемый тип должен быть распарсен из исходников или сформирован макросом (т.е. не быть из внешней сборки).

ME>а как в немерле решалась проблема кольцевых зависимостей, если там и правда можно читать из далекого класса? (т.е. у нас кто-то издалека пытался прочесть но не прочел -- нет у нас такого, потом мы такого сгенерили, потом полезли читать у того дальнего класса, а у него нет, так как он не прочел у нас)


Такой проблемы нет, так как любое изменение делается в TypeBuilder-е описывающем конкретный тип. Если кто-то туда что-то добавил, то тот кто будет читать после увидит эти изменения.

ME>или она вообще не ставилась?


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

Решается она за счет стадий. Макросы которые хотят читать результат работы других макросов должны работать на более поздних стадиях. Если макросы знаю друг о друге (один писался после другого), то всегда можно решить подобные проблемы. Если макросы писались параллельно и на эту проблему никто не обращал внимания, то возможно, что один макрос не будет видеть результата деятельности другого.

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

ME>или модель затачивалась на "пишем куда угодно, читаем локально"?


В Н1 модель полностью императивная. Пишем и читаем что хотим.

ME>вообще, жду рассказа про модель примерно такими словами, как я только что написал -- что макросы умеют, что неумеют, что не рассматривалось -- потому что то, что я читал, это какая-то конкретика, которая без общего взгляда мне совершенно не понятна


Ты лучше не жди чудесного объяснения. Мы все равно будем говорить на разных языках, так как исходим из разных отправных знаний. Лучше просто изучи основы и попробуй сам писать макросы. Лучше всего сделать это на базе некоторой, интересной тебе, задачи. Это даст тебе полное представление.

ME>а да -- еще желательно кинуть ссылку на списочек макросов "как называется, че делает"


http://nemerle.org/wiki/Accessor_macros (сбоку список макросов). Список, к сожалению, не полный. Но для начала хватит.
Но начинать лучше с прочтения статей. Благо их на русском до фига. Можно прочесть Язык Немерле:
Часть 1
Автор(ы): Владислав Юрьевич Чистяков
Дата: 24.09.2009
Эта статья открывает цикл статей, посвященных обучению языку программирования Nemerle. Имеющиеся статьи об этом языке предполагают, что программист хорошо знаком с Microsoft .NET Framework и языком программирования C#. Данный же цикл статей, напротив, рассчитан на людей, не знакомых ни с тем, ни с другим, и может быть даже применен для изучения программирования как такового. Новичкам в программировании может потребоваться помощь людей, уже знающих программирование.

Часть 2
Автор(ы): Чистяков Владислав Юрьевич
Дата: 30.06.2010
Неформальное введение в язык программирования Nemerle. В этой части, на базе примера «калькулятор», описываются типы данных variant и class.

Часть 3
Автор(ы): Чистяков Владислав Юрьевич
Дата: 25.07.2010
Неформальное введение в язык программирования Nemerle. В этой части, на базе примера «калькулятор», описываются типы данных variant и class.

Часть 5
Автор(ы): Чистяков Владислав Юрьевич
Дата: 22.09.2011
Данная часть посвящена макросам Nemerle.

Эта работа не закончена, но зато наиболее полная и последовательная.

ME>и еще вопрос -- а макросы умеют принимать в качестве аргумента название класса, или его поля?


Да. Макрос может принимать в качестве аргумента любое выражение. А уже выражение может быть интерпретировано как имя класса или поля.

ME>с проверкой на наличие?


Да. Только проверку придется делать самостоятельно.

ME> а если этого поля пока что нет, и оно будет дописано другим макросом?


То твой макрос его не увидит.

ME>например так:

ME>
ME>  [StructuralEquality<exclude<StartPos>>, StructuralHashCode]
ME>  public struct NToken
ME>  {
ME>    public StartPos : int { get; }
ME>    public EndPos   : int { get; }
ME>


Не понял причем тут этот пример, но именно это макрос StructuralEquality. Только синтаксис другой. В Н параметры типов через [] задаюттся. А аргументы макросов просто в круглых скобках.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[17]: Тюринг-полные ли шаблоны C++?
От: VladD2 Российская Империя www.nemerle.org
Дата: 10.02.12 14:31
Оценка:
Здравствуйте, WolfHound, Вы писали:

ME>>или такой текст уже есть? тогда ссылку

WH>http://rsdn.ru/summary/3766.xml
WH>Смотри "Макросы Nemerle – расширенный курс" в 4х частях.

Вот это совершенно не разумня ссылка. Это материал для тех кто уже знает что такое макросы и хочет погрузиться по глубже.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[7]: Тюринг-полные ли шаблоны C++?
От: VladD2 Российская Империя www.nemerle.org
Дата: 10.02.12 14:35
Оценка:
Здравствуйте, m e, Вы писали:

ME>
ME>class T {
ME>  int a;
ME>  int b;
ME>  int c;
ME>  static if( hasMember!(Х, "y") ) {
ME>    int z;
ME>  }
ME>}
ME>


А можно пояснить какой смысл в этой действии? Ведь результат будет всегда один и тот же, так как поле или будет, или не будет. Какая-то условная компиляция получается. На фиг такое нужно на практике?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[8]: Тюринг-полные ли шаблоны C++?
От: FR  
Дата: 10.02.12 14:44
Оценка:
Здравствуйте, VladD2, Вы писали:


VD>А можно пояснить какой смысл в этой действии? Ведь результат будет всегда один и тот же, так как поле или будет, или не будет. Какая-то условная компиляция получается. На фиг такое нужно на практике?


В шаблонах вполне осмысленно, конечно если тип X обобщенный.
Re[12]: Тюринг-полные ли шаблоны C++?
От: VladD2 Российская Империя www.nemerle.org
Дата: 10.02.12 15:04
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Напомню, что BindFixedType имеет тип PExpr -> FixedType.


Это мелкие детали. В макрос тоже обычно не строки передаются. В прочем строку в PExpr тоже не долго превратить. Так что написать для себя (если очень нужно) вариант принимающих строку — это не проблема.

FixedType в FixedType.Class тоже не сложно превратить. Можно фатальную ошибку выдавать, если это не пользовательский тип.

WH>И у FixedType нет метода GetFields.


А если так:
fixedType.TipeInfo?.GetFields() ?? []

?

WH>Перегрузки, которая принимают строку у BindFixedType тоже нет.


См. выше.

WH>С типами из текущей сборки (TypeBuilder) и теми которые лежат во внешних сборках (LibraryReference.ExternalTypeInfo) нужно обращаться по-разному.


Зачем? Не надо. Всю информацию можно получить через TypeInfo. Приведение к TypeBuilder потребуется только, если захочешь изменить тип. Но оно и разумно.

WH>Короче мороки много.


Нет тут особой мороки. Не выдумывай. Максимум пару функций-помощников придется написать.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[16]: Тюринг-полные ли шаблоны C++?
От: DarkGray Россия http://blog.metatech.ru/post/ogni-razrabotki.aspx
Дата: 10.02.12 16:07
Оценка:
ME>или она вообще не ставилась?
ME>или модель затачивалась на "пишем куда угодно, читаем локально"?

на сколько я понимаю, такой уровень постановки вообще не рассматривался.

задача ставилась как: давайте сделаем так, чтобы на уровне компиляции можно было выполнять произвольный набор преобразований:
Ast -> код1 -> Ast
Ast -> код2 -> Ast
Ast -> код3 -> Ast
и т.д.

при этом никаких ограничений ни на порядок вызова код1, код2, код3 и т.д., ни на "масштаб" ast-а, ни на набор использованных инструкций в ast-е не накладывается, а процветает сплошная анархия.
Re[13]: Тюринг-полные ли шаблоны C++?
От: WolfHound  
Дата: 10.02.12 19:38
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>А если так:

VD>
VD>fixedType.TipeInfo?.GetFields() ?? []
VD>

VD>?
Ух ты костыль какой.

VD>Зачем? Не надо. Всю информацию можно получить через TypeInfo. Приведение к TypeBuilder потребуется только, если захочешь изменить тип. Но оно и разумно.

То-то мне пришлось огород городить...
https://github.com/rampelstinskin/ParserGenerator/blob/master/Nemerle.Parser.Macro/Compiler/GrammarCompiler/Typing/LoadExternalGrammars.n
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[14]: Тюринг-полные ли шаблоны C++?
От: VladD2 Российская Империя www.nemerle.org
Дата: 10.02.12 20:11
Оценка:
Здравствуйте, WolfHound, Вы писали:

VD>>А если так:

VD>>
VD>>fixedType.TypeInfo?.GetFields() ?? []
VD>>

VD>>?
WH>Ух ты костыль какой.

Какой на фиг костыль?

VD>>Зачем? Не надо. Всю информацию можно получить через TypeInfo. Приведение к TypeBuilder потребуется только, если захочешь изменить тип. Но оно и разумно.

WH>То-то мне пришлось огород городить...
WH>https://github.com/rampelstinskin/ParserGenerator/blob/master/Nemerle.Parser.Macro/Compiler/GrammarCompiler/Typing/LoadExternalGrammars.n

Это не только огород, но еще и потенциально опасный код. Когда будем переходить на бэкэнды ExternalTypeInfo из пользовательского кода доступен не будет. Так что советую тебе пока не поздно перенести функцию в компилятор (где ей самое место). И возвращать он должен TypeInfo, а не ExternalTypeInfo.

Ну, а к поиску типов по имена этот код не имеет отношения.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[17]: Тюринг-полные ли шаблоны C++?
От: m e  
Дата: 11.02.12 20:01
Оценка:
Здравствуйте, VladD2, Вы писали:

Удален оверквотинг

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


бугага (особенно про троллинг)

я уже 2 (два, ДВА!) раза писал о проблеме с++ -- то, что шаблоны не все могут прочитать -- и теперь приходится писать об этом в третий раз

можно было бы уже и сделать вывод о том, что "в мои задачи не входит любой ценой доказать преимущества ... С++"

VD>Кстати, как показывает практика, именно из С++-ников получаются отличные немерлисты . Так что если ты пришел разобраться, то милость просим в наше братство. Мы тебе поможем и ты сможешь по достоинству оценить технологию.


я действительно пришел разобраться, пора уже

прошлые мои попытки разобраться путем чтения статей на rsdn и на сайте немерле года 2-3 назад провалились

т.е. сама по себе идея генережа в компайл-тайме (путем чтения и записи AST) здрава, и воспринимается влет; квазицитирование это по-моему слегка уход в сторону, но опять воспринимается легко

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

VD>Если бы Вольфхаунд считал бы, что аналог его парсера можно было бы сделать на С++, то зачем бы ему вообще было связываться с Немерлом?


это не аргумент

но раз вы оба постоянно нажимаете на эту тему, давайте разберем ее подробнее

технология для этого емнип в с++ называется expression templates, подробнее я напишу вольфхауну

(да, это только первый ответ, дальше будут и другие)
Re[18]: Тюринг-полные ли шаблоны C++?
От: WolfHound  
Дата: 12.02.12 08:40
Оценка:
Здравствуйте, m e, Вы писали:

ME>технология для этого емнип в с++ называется expression templates, подробнее я напишу вольфхауну

Можешь не трудиться. И про метаизвращения на шаблонах не хуже тебя знаю.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[19]: Тюринг-полные ли шаблоны C++?
От: m e  
Дата: 12.02.12 15:03
Оценка:
WH> И про метаизвращения на шаблонах не хуже тебя знаю.

тогда скажу то, что возможно ты не знаешь

на с++11 стало можно статически получать доступ к содержимому строковых литералов, скажем можно написать
auto r = "[a-z]+[a-z0-9]+"_regex;

и распарсить рег.выр. в компайл-тайме (оно передается посимвольно как аргумент вариадического шаблона)

да, кстати, на уровне выражений получать АСТ вместо значения емнип можно и в скале, и одерски трудился, городил что-то похожее на expression templates на имплицитах

еще в с++ можно получать АСТ без "шума" на запихивание литералов в свой класс, т.к. литерал уже класс

WH>Можешь не трудиться.


хм, не трудиться...

я уж мягко предложил владу отказаться от *последующих* его явно неверных выпадов в адрес с++, но он не стал это делать

проблема в том, что влад и в меньшей степени ты записываете в уникальные достоинтства немерле то, что делается на с++, и при том, что достоинтства немерле перед с++ и правда имеются, и даже были мной упомянуты

впрочем, предложение принимаю, при условии отсутствия последующих явно неверных высказываний в адрес с++... все же мне как-то больше нравится просветляться самому, чем Нести Просветление В Массы

кстати -- в немерле можно получить доступ к значению строкового литерала в компайл-тайме?
Re[10]: Тюринг-полные ли шаблоны C++?
От: m e  
Дата: 12.02.12 15:13
Оценка:
VD>Если он обобщенный, то проверять ты будешь не левых тип Х который по имени будешь искать, а параметр типов.
VD>Меня интересует смысл именно этого кода. Я его не могу уловить.

а в немерле есть принципиальная разница -- тип известен как параметр шаблона (или там-его-аналого), или просто по имени?
Re[20]: Тюринг-полные ли шаблоны C++?
От: WolfHound  
Дата: 12.02.12 15:36
Оценка:
Здравствуйте, m e, Вы писали:

ME>проблема в том, что влад и в меньшей степени ты записываете в уникальные достоинтства немерле то, что делается на с++, и при том, что достоинтства немерле перед с++ и правда имеются, и даже были мной упомянуты

Разница между шаблонами С++ и макросами немерле как между машиной Тьюринга и промышленным языком программирования.
В теории на МТ можно сделать все. Но на практике задолбаешься так что

ME>кстати -- в немерле можно получить доступ к значению строкового литерала в компайл-тайме?

И после этого ты хочешь сказать что читал статьи по намерле?
http://nemerle.org/wiki/index.php?title=SQL_macros
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[21]: Тюринг-полные ли шаблоны C++?
От: m e  
Дата: 12.02.12 16:38
Оценка:
WH>И после этого ты хочешь сказать что читал статьи по намерле?

да, в районе 3 лет назад

з.ы. напомню, что кое-какие мои вопросы остаются пока без ответа
Re[18]: Тюринг-полные ли шаблоны C++?
От: m e  
Дата: 12.02.12 16:39
Оценка:
VD>Вот это совершенно не разумня ссылка. Это материал для тех кто уже знает что такое макросы и хочет погрузиться по глубже.

читать надо именно это, потому что предыдущие части похожи на жидкую манную кашу с кусочками гранита

а в 4-й хоть твердость примерно равномерная
Re[11]: Тюринг-полные ли шаблоны C++?
От: VladD2 Российская Империя www.nemerle.org
Дата: 13.02.12 05:30
Оценка:
Здравствуйте, m e, Вы писали:

ME>а в немерле есть принципиальная разница -- тип известен как параметр шаблона (или там-его-аналого), или просто по имени?


Естественно. Одно дело искать тип (да еще по не полному имени), и другое обращаться к конкретному параметру типа.

Кроме того в Немерле нет шаблонов. Дженерики же работают в рантайме и анализировать парамер типов из этого типа особого смысла не имеет, так как он будет описывать только те констрэйны, что заданы и ничего не скажет о рантайм-типе.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[10]: Тюринг-полные ли шаблоны C++?
От: jazzer Россия Skype: enerjazzer
Дата: 13.02.12 05:44
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Меня интересует смысл именно этого кода. Я его не могу уловить.


Ну например, если у тебя есть поле типа char*, то автоматически добавляется поле с длиной строки.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[11]: Тюринг-полные ли шаблоны C++?
От: VladD2 Российская Империя www.nemerle.org
Дата: 13.02.12 05:57
Оценка:
Здравствуйте, jazzer, Вы писали:

VD>>Меня интересует смысл именно этого кода. Я его не могу уловить.


J>Ну например, если у тебя есть поле типа char*, то автоматически добавляется поле с длиной строки.


Если бы ты вдумчиво прочел тему, то понял бы, что твой ответ не в кассу.
Вопрос был — зачем делать добавление членов в тип зависимым от чего-то из другого типа? Это может иметь смысл если язык дремуч как С++ и в нем ест инклюды. Но в модульном языке — это совершенно бессмысленно.

С параметрами типов дженериков это тоже смысл не имеет, так как из конкретные значения становятся доступны только в рнтайме. Так что осмыслен данный код может быть только для шаблонов. Но как раз то их в Н и нет.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[19]: Тюринг-полные ли шаблоны C++?
От: VladD2 Российская Империя www.nemerle.org
Дата: 13.02.12 06:14
Оценка:
Здравствуйте, m e, Вы писали:

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


ME>читать надо именно это, потому что предыдущие части похожи на жидкую манную кашу с кусочками гранита

ME>а в 4-й хоть твердость примерно равномерная

Тебе ни одну из этих частей читать не надо. Это все равно что начинать учить С++ с Александревсковских трудов. Ничего не поймешь, и толку будет — 0.

И вообще, просто читать смысла нет. Надо пробовать. Прочти 5-ю часть
Автор(ы): Чистяков Владислав Юрьевич
Дата: 22.09.2011
Данная часть посвящена макросам Nemerle.
"Язык Nemerle", и если есть проблемы в понимании самого языка, то предыдущие части. Этого должно хватить для старта. Далее надо взять и написать, что-то своими руками.

Все скептики критикующие Н или не написали на нем ни строчки, или побаловались с примерами и забросили. Так что единственный вариант разобраться — это использовать его для реальных задач.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[12]: Тюринг-полные ли шаблоны C++?
От: jazzer Россия Skype: enerjazzer
Дата: 13.02.12 06:19
Оценка:
Здравствуйте, VladD2, Вы писали:

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


VD>>>Меня интересует смысл именно этого кода. Я его не могу уловить.


J>>Ну например, если у тебя есть поле типа char*, то автоматически добавляется поле с длиной строки.


VD>Если бы ты вдумчиво прочел тему, то понял бы, что твой ответ не в кассу.

VD>Вопрос был — зачем делать добавление членов в тип зависимым от чего-то из другого типа? Это может иметь смысл если язык дремуч как С++ и в нем ест инклюды. Но в модульном языке — это совершенно бессмысленно.

Я же привел пример — если в этом самом типе есть поле типа char*.
Причем тут инклюды, я вообще не понял. Какая разница, каким образом подключается информация о типах — через инклуд или как-то иначе?
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[20]: Тюринг-полные ли шаблоны C++?
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 13.02.12 07:14
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Все скептики критикующие Н или не написали на нем ни строчки, или побаловались с примерами и забросили. Так что единственный вариант разобраться — это использовать его для реальных задач.


А есть примеры решения реальных задач на nemerle?
Re[13]: Тюринг-полные ли шаблоны C++?
От: VladD2 Российская Империя www.nemerle.org
Дата: 13.02.12 12:02
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Я же привел пример


А надо было для начала почитать обсуждение.

J>- если в этом самом типе есть поле типа char*.


Да какая разница какого типа поле? Вопрос был в том, зачем делать в одном типе что-то на основании того, что что-то есть в некотором другом типе, причем этот тип нужно искать по имени. Тут вопрос в том как получить такое имя и где такой подход может пригодиться.

J>Причем тут инклюды, я вообще не понял. Какая разница, каким образом подключается информация о типах — через инклуд или как-то иначе?


Притом, что только при условии, что код может включаться в проект по разному нужно какая-то условная генерация. И то трудно представить как это осмысленно использовать. Это уже какие-то варианты на тему условной компиляции.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[21]: Тюринг-полные ли шаблоны C++?
От: VladD2 Российская Империя www.nemerle.org
Дата: 13.02.12 12:05
Оценка:
Здравствуйте, gandjustas, Вы писали:

VD>>Все скептики критикующие Н или не написали на нем ни строчки, или побаловались с примерами и забросили. Так что единственный вариант разобраться — это использовать его для реальных задач.


G>А есть примеры решения реальных задач на nemerle?


Это офтопик. Да и отвечать по сотому разу на один и тот же вопрос довольно глупо. Примеров масса. Все кого в гуле не забанили должны найти. Если уж с гуглем совсем проблемы, заходишь в соответствующий форум и задаешь вопрос.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[12]: Тюринг-полные ли шаблоны C++?
От: m e  
Дата: 13.02.12 13:38
Оценка:
ME>>а в немерле есть принципиальная разница -- тип известен как параметр шаблона (или там-его-аналого), или просто по имени?

VD>Естественно. Одно дело искать тип (да еще по не полному имени), и другое обращаться к конкретному параметру типа.


это надо было сразу сказать, не дожидаясь моего вопроса

тем не менее, это похоже мало что меняет и мне не понятно -- lookup по неполному имени должен быть реализован в компиляторе -- тогда почему он плохо доступен?

VD>Кроме того в Немерле нет шаблонов. Дженерики же работают в рантайме и анализировать парамер типов из этого типа особого смысла не имеет, так как он будет описывать только те констрэйны, что заданы и ничего не скажет о рантайм-типе.


а если параметром дженерика идет value type как в дотнете, то дженерик специализируется под него или нет?
Re[13]: Тюринг-полные ли шаблоны C++?
От: VladD2 Российская Империя www.nemerle.org
Дата: 13.02.12 13:55
Оценка:
Здравствуйте, m e, Вы писали:

ME>это надо было сразу сказать, не дожидаясь моего вопроса


Не уже ли это не очевидно?

ME>тем не менее, это похоже мало что меняет и мне не понятно -- lookup по неполному имени должен быть реализован в компиляторе -- тогда почему он плохо доступен?


Он и реализован. Но надо понимать о чем говоришь. Чтобы делать связывание не полного имени нужно иметь окружение в котором описаны открытые пространства имен и типы. В Немерле это называется GlobalEnv. Он автоматически формируется парсером и присваивается ко всему что может иметь в себе ссылки на имена.

VD>>Кроме того в Немерле нет шаблонов. Дженерики же работают в рантайме и анализировать парамер типов из этого типа особого смысла не имеет, так как он будет описывать только те констрэйны, что заданы и ничего не скажет о рантайм-типе.


ME>а если параметром дженерика идет value type как в дотнете, то дженерик специализируется под него или нет?


Немерли есть дотнет. И в дотнете для дженериков предусмотрены исключительно констрэйны. Специализируются же дженерики уже в рантайме (самим рантаймом). По этому изнутри дженерика невозможно узнать реальный тип (разве что через рефлексию).

В местах применения дженерик-типов можно узнать что аз параметр типов задан дженерик-типу. Но не из самого дженерика.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[20]: Тюринг-полные ли шаблоны C++?
От: m e  
Дата: 13.02.12 14:07
Оценка:
VD>И вообще, просто читать смысла нет. Надо пробовать. Прочти 5-ю часть
Автор(ы): Чистяков Владислав Юрьевич
Дата: 22.09.2011
Данная часть посвящена макросам Nemerle.
"Язык Nemerle", и если есть проблемы в понимании самого языка, то предыдущие части. Этого должно хватить для старта. Далее надо взять и написать, что-то своими руками.


5-ю я вообще не видел, но см. ниже

VD>Все скептики критикующие Н или не написали на нем ни строчки, или побаловались с примерами и забросили. Так что единственный вариант разобраться — это использовать его для реальных задач.


меня не устраивает этот якобы единственный вариант

мне нужно прочесть *описание* языка (я не говорю стандарт, хотя бы описание)

это значит, что хотя бы должна быть определена терминология -- т.е. все фазы компиляции должны быть названы словами русского или английского языка (а не названиями процедур, функций, энумов или х.з. чего из исходного кода), и называться везде одинаково -- скажем, фаза WithTypedMembers части 5-й соответствует какой из фаз 1-9 из http://www.rsdn.ru/article/nemerle/MacrosExtCoursePart4.xml
Автор(ы): Владислав Юрьевич Чистяков
Дата: 03.09.2009
В данной части статьи рассказывается о том, как работает система вывода типов Nemerle, о том, как с ней могут взаимодействовать макросы Nemerle, и что это дает
? (при этом функции и т.д. *можно* называть по названиям фаз, но не наоборот)

то, что в http://www.rsdn.ru/article/nemerle/MacrosExtCoursePart4.xml
Автор(ы): Владислав Юрьевич Чистяков
Дата: 03.09.2009
В данной части статьи рассказывается о том, как работает система вывода типов Nemerle, о том, как с ней могут взаимодействовать макросы Nemerle, и что это дает
написано "6. Типизирует члены типов", заставляет вылезти из парсера, посмотреть, не сломался ли он, и продолжать движение вперед на скорости 5-10 км/ч

да, даже если "класс" и "тип" у вас одно и то же, то это как минимум непривычно; более того, я подозреваю, что у вас есть неклассовые типы, и должно было быть написано "6. Типизирует члены классов"

из описания языка должны быть выброшены куски исходного кода компилятора (хотя их конечно можно вынести на отдельные странички, на которые ведут ссылки из описания), и могут быть добавлены примеры на каждую фазу трансляции -- как выглядит полученное к тому времени AST

в целом, я думаю можно взять как раз последние части разных курсов, привести в порядок терминологию, может быть потребуется чуть пораскидать их куски по разделам и получится вполне пригодная к прочтению вещь
Re[22]: Тюринг-полные ли шаблоны C++?
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 13.02.12 14:14
Оценка:
Здравствуйте, VladD2, Вы писали:

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


VD>>>Все скептики критикующие Н или не написали на нем ни строчки, или побаловались с примерами и забросили. Так что единственный вариант разобраться — это использовать его для реальных задач.


G>>А есть примеры решения реальных задач на nemerle?


VD>Это офтопик. Да и отвечать по сотому разу на один и тот же вопрос довольно глупо. Примеров масса. Все кого в гуле не забанили должны найти. Если уж с гуглем совсем проблемы, заходишь в соответствующий форум и задаешь вопрос.


Не интересует не просто примеры кода, а именно примеры приложений. Даже если не очень настоящих, но тем не менее готовых и работающих. Именно приложений, а не библиотек.
Re[14]: Тюринг-полные ли шаблоны C++?
От: m e  
Дата: 13.02.12 14:19
Оценка:
ME>>это надо было сразу сказать, не дожидаясь моего вопроса

VD>Не уже ли это не очевидно?


ME>>тем не менее, это похоже мало что меняет и мне не понятно -- lookup по неполному имени должен быть реализован в компиляторе -- тогда почему он плохо доступен?


VD>Он и реализован. Но надо понимать о чем говоришь. Чтобы делать связывание не полного имени нужно иметь окружение в котором описаны открытые пространства имен и типы. В Немерле это называется GlobalEnv. Он автоматически формируется парсером и присваивается ко всему что может иметь в себе ссылки на имена.


да, неочевидно, и более того, неясно даже после твоего разъяснения -- *как* все это мешает вызвать уже имеющуюся функцию (лично для себя я предполагаю, что дело в фазах компиляции)

VD>В местах применения дженерик-типов можно узнать что аз параметр типов задан дженерик-типу. Но не из самого дженерика.


это решение выглядит более-менее обоснованным для ref types, но для значений -- нет

как мне написать дженерик, которому в качестве типа-параметра T можно подсунуть как float, так и double, но для того, чтобы закончить итерации, мне нужно внутри дженерика знать epsilon такой что
T t = 1; 
assert( t+(epsilon<T>)==t );
Re[14]: Тюринг-полные ли шаблоны C++?
От: m e  
Дата: 13.02.12 14:26
Оценка:
в связи с постом gandjustas -- меня абсолютно не интересует, что на немерле написано

писать можно на чем угодно -- даже на РНР 3
Re[20]: Тюринг-полные ли шаблоны C++?
От: m e  
Дата: 13.02.12 14:40
Оценка:
далее, в http://www.rsdn.ru/article/nemerle/MacrosExtCoursePart4.xml
Автор(ы): Владислав Юрьевич Чистяков
Дата: 03.09.2009
В данной части статьи рассказывается о том, как работает система вывода типов Nemerle, о том, как с ней могут взаимодействовать макросы Nemerle, и что это дает


> 7. Типизирует тела членов.


имеется в виду тела методов? или у полей тоже могут быть тела? или же имеются в виду тела геттеров и сеттеров тоже? но тогда получается, что геттеры и сеттеры являются членами, и поэтому должны относиться к методам?

короче -- еще раз -- реквестирую терминологию
Re[23]: Тюринг-полные ли шаблоны C++?
От: CodingUnit Россия  
Дата: 13.02.12 15:25
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Не интересует не просто примеры кода, а именно примеры приложений. Даже если не очень настоящих, но тем не менее готовых и работающих. Именно приложений, а не библиотек.


Есть готовые работающие приложения, в своей организации я применял Немерле для написания OPC-сервера для сбора данных с внешних устройств подключенных к портам и организации обмена с OPC-клиентами, scada-системами. Также обычные пользовательские приложения Windows Forms, очень удобно на нем пишутся, писал что то типа монитора сбора данных и программы для калибровки. Собираюсь еще в некоторых проектах его использовать, все программы где применим C# очень легко пишутся. Я думаю многие где возможно применяют его в практике.
Re[21]: Тюринг-полные ли шаблоны C++?
От: VladD2 Российская Империя www.nemerle.org
Дата: 13.02.12 15:40
Оценка:
Здравствуйте, m e, Вы писали:

VD>>Так что единственный вариант разобраться — это использовать его для реальных задач.


ME>меня не устраивает этот якобы единственный вариант


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

ME>мне нужно прочесть *описание* языка (я не говорю стандарт, хотя бы описание)


Читай Язык Немерле. Я только что вложил шестую часть
Автор(ы): Чистяков Владислав Юрьевич
Дата: 20.02.2012
Данная часть посвящена синтаксису Nemerle.
посвященную синтаксису.

ME>это значит, что хотя бы должна быть определена терминология -- т.е. все фазы компиляции должны быть названы словами русского или английского языка (а не названиями процедур, функций, энумов или х.з. чего из исходного кода), и называться везде одинаково -- скажем, фаза WithTypedMembers части 5-й соответствует какой из фаз 1-9 из http://www.rsdn.ru/article/nemerle/MacrosExtCoursePart4.xml
Автор(ы): Владислав Юрьевич Чистяков
Дата: 03.09.2009
В данной части статьи рассказывается о том, как работает система вывода типов Nemerle, о том, как с ней могут взаимодействовать макросы Nemerle, и что это дает
? (при этом функции и т.д. *можно* называть по названиям фаз, но не наоборот)


Все везде называется одинаково. Как я понимаю, то что ты называешь 1-9 — это просто перечисление этапов компиляции. Они к фазам макроса прямого отношения не имеют. Так что не надо искать тут соотвествие.

Хотя, еще раз повторяю, что читать "Макросы Nemerle – расширенный курс" можно только после глубокого и серьезного практического использования макросов в течении, хотя бы, месяца. Это курс для тех кто уже в теме и хочет углубить свои знания, а не как для начинающих.

ME>то, что в http://www.rsdn.ru/article/nemerle/MacrosExtCoursePart4.xml
Автор(ы): Владислав Юрьевич Чистяков
Дата: 03.09.2009
В данной части статьи рассказывается о том, как работает система вывода типов Nemerle, о том, как с ней могут взаимодействовать макросы Nemerle, и что это дает
написано "6. Типизирует члены типов", заставляет вылезти из парсера, посмотреть, не сломался ли он, и продолжать движение вперед на скорости 5-10 км/ч


Вообще ничего не понял. Откуда вылезти? Куда двигаться? О чем речь то?

ME>да, даже если "класс" и "тип" у вас одно и то же, то это как минимум непривычно; более того, я подозреваю, что у вас есть неклассовые типы, и должно было быть написано "6. Типизирует члены классов"


Я же не виноват, что тебе не привычно, что кроме классов есть еще и другие типы? Привыкай. В дотнете есть структуры и перечисления. В Немерле в добавок есть вариантные типы. Все это не классы, но пользовательские типы.

ME>из описания языка должны быть выброшены куски исходного кода компилятора


А кто тебе сказал что "Макросы Nemerle – расширенный курс" — это описание языка? Я устал повторять, что это продвинутый материал. Его просто не надо читать в начале пути. У Вользфхаунад есть дна проблема. Он все судит по себе. В том числе и доступность материалов. Но то, в отличии от тебя, уже несколько лет сам пишет макросы. И ему расширенный курс в самый раз.

ME>(хотя их конечно можно вынести на отдельные странички, на которые ведут ссылки из описания), и могут быть добавлены примеры на каждую фазу трансляции -- как выглядит полученное к тому времени AST


Просто читай то что тебе предлагают и не перепрыгивай через стадии обучения. Тогда все будет ОК.

ME>в целом, я думаю можно взять как раз последние части разных курсов, привести в порядок терминологию, может быть потребуется чуть пораскидать их куски по разделам и получится вполне пригодная к прочтению вещь


Еще раз, с терминологией все в порядке. Если что-то не так, то приводи конкретные абзацы и объясняй, что там не так. Будем думать надо ли там что-то править. Пока что я проблем не видел. Терминологию подбирали вдумчиво.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[23]: Тюринг-полные ли шаблоны C++?
От: VladD2 Российская Империя www.nemerle.org
Дата: 13.02.12 15:42
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Не интересует не просто примеры кода, а именно примеры приложений. Даже если не очень настоящих, но тем не менее готовых и работающих. Именно приложений, а не библиотек.


Тебе предупреждение за офтопик не пришло? Или ты решил, что такую вещь как предупреждение модератонов можно игнорировать?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[22]: Тюринг-полные ли шаблоны C++?
От: m e  
Дата: 13.02.12 16:28
Оценка:
ME>>меня не устраивает этот якобы единственный вариант

VD>Тогда завязывай с программированием.


спасибо, о Великий Гуру, за Бесценный Совет

но я продолжу самостоятельно выбирать, что мне изучать теоретически, а что использовать на практике

если интересно почему так -- я не использую на практике то, что не понимаю в достаточной степени

степень достаточности понимания я определяю самостоятельно

ME>>мне нужно прочесть *описание* языка (я не говорю стандарт, хотя бы описание)


VD>Читай Язык Немерле. Я только что вложил шестую часть
Автор(ы): Чистяков Владислав Юрьевич
Дата: 20.02.2012
Данная часть посвящена синтаксису Nemerle.
посвященную синтаксису.


да, это обязательно прочту -- хотя тут скорее не синтаксис, а семантика


ME>> ... фаза WithTypedMembers части 5-й ...


VD>Все везде называется одинаково. Как я понимаю, то что ты называешь 1-9 — это просто перечисление этапов компиляции. Они к фазам макроса прямого отношения не имеют.


упс?!
в 5-й части написано:

> Использование фазы компиляции WithTypedMembers

> Выпадающий список «Macro Phase» позволяет задать стадию компиляции, на которой будет вызываться макро-атрибут.

замечу, *стадию компиляции*

(объяснение опять же из этой части приводит к предположению, что WithTypedMembers >= 7)

VD>Так что не надо искать тут соотвествие.


почему не надо? и там и там разговор идет о некой последовательности фаз/стадий/шагов/... компиляции с весьма *похожими* характеристиками

что я путаю?

VD>Еще раз, с терминологией все в порядке. Если что-то не так, то приводи конкретные абзацы и объясняй, что там не так.


вот и привожу, см. выше в этом посте
Re[22]: Тюринг-полные ли шаблоны C++?
От: m e  
Дата: 13.02.12 17:03
Оценка:
VD>Я же не виноват, что тебе не привычно, что кроме классов есть еще и другие типы? Привыкай.

вполне себе привычно -- типы функций например или тип int в плюсах -- это явно не класс

непривычно то, что речь идет о членах типа вообще -- скажем, у типа int в плюсах не может быть членов

подробнее отвечу когда прочту http://www.rsdn.ru/article/nemerle/TheNemerle-part-6/Nemerle-Lang-part-6.rsdnml.xml
Автор(ы): Чистяков Владислав Юрьевич
Дата: 20.02.2012
Данная часть посвящена синтаксису Nemerle.


но после беглого взгляда на "члены типа" уже возникает вопрос -- там указано, какие из типов могут иметь члены, а какие нет? скажем, может ли функциональный тип иметь члены (кажется что нет, но кто вас знает)? а тип массива? (тут уже не поставлю ни на что) а если может, то происходит ли там "7. Типизирует тела членов."?

VD>А кто тебе сказал что "Макросы Nemerle – расширенный курс" — это описание языка?


я не утвеждал, что это описание

где лежит именно описание языка -- не только синтаксиса и немного семантики (ты уже дал ссылку), а семантики в части макросов? (да, там будет скорее всего операционная семантика, но это вполне меня устраивает)
Re[22]: Тюринг-полные ли шаблоны C++?
От: m e  
Дата: 13.02.12 17:17
Оценка:
VD> В нашем деле чтобы что-то освоить нужно обязательно начать использовать это что-то на практике.

я считаю, что на практике в прогах от 1000 строк можно использовать только тот язык программирования, у которого есть описание языка, а не рассказ "что делает вот этот код в нашем компиляторе" (или интерпретаторе, если речь не про немерле)

понятно, что это вовсе не обзательно должно быть формальное описание, и даже не обязательно стандарт, но описание быть должно

т.е. да, можно пописать кусочки кода в 30 строк, но на столь малых прогах все по-другому -- скажем, уже нет профита юзать статическую типизацию, и даже возможно наоборот, есть смысл использовать языки без нее и без деклараций переменных -- так что немерле тут оценить вряд ли удастся
Re[21]: Тюринг-полные ли шаблоны C++?
От: VladD2 Российская Империя www.nemerle.org
Дата: 13.02.12 18:22
Оценка:
Здравствуйте, m e, Вы писали:

ME>далее, в http://www.rsdn.ru/article/nemerle/MacrosExtCoursePart4.xml
Автор(ы): Владислав Юрьевич Чистяков
Дата: 03.09.2009
В данной части статьи рассказывается о том, как работает система вывода типов Nemerle, о том, как с ней могут взаимодействовать макросы Nemerle, и что это дает


>> 7. Типизирует тела членов.


ME>имеется в виду тела методов? или у полей тоже могут быть тела?


У полей есть инициализирующие выражения. Они в итоге переписываются в конструкторы, но логически это выражения связанные

ME>или же имеются в виду тела геттеров и сеттеров тоже?


Свойства тоже члены. Так что когда говорится о телах членов, то имеется в виду и гетеры с сетеры в том числе.

ME>но тогда получается, что геттеры и сеттеры являются членами, и поэтому должны относиться к методам?


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

ME>короче -- еще раз -- реквестирую терминологию


Она есть. Просто ты не привык. Разжевать все нереально. Так что просто спрашивай, а мы будем отвечать. Потом в ФАК добавим.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[15]: Тюринг-полные ли шаблоны C++?
От: VladD2 Российская Империя www.nemerle.org
Дата: 13.02.12 18:25
Оценка:
Здравствуйте, m e, Вы писали:

ME>в связи с постом gandjustas -- меня абсолютно не интересует, что на немерле написано


Этот товарищ просто достал. Он с периодичностью будильника этот вопрос к месту и не к месту задает. Причем когда ему выдают список, то он начинает с ним бороться. В общем, у него одна задача — обосновать для себя то почему ему ни в коем случае с этим не надо разбираться.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[22]: Тюринг-полные ли шаблоны C++?
От: m e  
Дата: 13.02.12 21:22
Оценка:
вот, в результате дешифровки и допроса источников с особым пристрастием, у меня получилось вот это
в скобках подчеркнутым выделены мои вопросы и замечания
какие тут ошибки?

для начала назовем агрегатами (aggregates) все, что может иметь члены (полный список должен быть в описании языка); агрегаты могут поддерживать наследование (или всегда поддерживают наследование?)


Фаза импорта. Считывается описание типов, импортируемых из внешних сборок.

Фаза пре-парсинга. Производится пре-парсинг файлов, получая при этом дерево токенов, свернутых по скобкам (че такое скобки? я догадываюсь, но не ясно зачем это надо -- у вас ассоциативность оператора может зависеть от типов, или зачем?). На этом этапе формируется так называемое «окружение»(где жаргонный термин?). В окружении сохраняется информация об открытых пространствах имен, а значит, доступных макросах и операторах.

Фаза парсинга. Производит парсинг. Он состоит из создания AST верхнего уровня (TopDeclaration) (нет четкого примера в описании синтаксиса; приведу свой оттуда: public class MyList[T] : IList[T] {....} ) и создания нетипизированного AST тел членов (PExpr).

Фаза перед наследованием. Запуск макросов BeforeInheritance.

Фаза наследования. Строится дерево наследования агрегатов. Дерево строится на основании информации об импортированных из других сборок агрегатов и на основании TopDeclaration разобранных исходных файлов.

(выброшеная фаза: Производит разрешение наследования (задает отношения между типами), т.к. она излишняя)

Фаза перед типизацией членов. Запуск макросов BeforeTypedMembers.

Фаза типизации членов. Типизируются члены агрегатов, т.е. связываются текстовые (че??? у нас же вроде AST везде?) описания типов параметров и возвращаемых значений с типами из дерева агрегатов. Компилятор не допускает вывода типов для членов агрегатов, поэтому после этого этапа становятся известными типы всех членов. Для методов это означает, что становятся известны типы аргументов и типы возвращаемых значений.

Фаза типизации тел методов. (К методам относятся и конструкторы). Инициализаторы полей, а также getter-ы/setter-ы свойств преобразуются в методы (так, инициализаторы полей реально копируются в конструкторы агрегатов). Затем типизируются тела методов в агрегатах -- раскрываются макросы WithTypedMembers и производится вывод типов. Это самая сложная фаза компиляции. На выходе этой фазы тела методов содержат типизированный AST (TExpr). Состоит из следующих подфаз:


Фаза оптимизации. Производятся различные преобразования над типизированым AST, оптимизация и т.п. (что и т.п.?)

Фаза генерации. Производится генерация IL.
Re[22]: Тюринг-полные ли шаблоны C++?
От: m e  
Дата: 13.02.12 21:33
Оценка:
я слегка пошлифовал твой текст, но даже и в моей редакции он порядком ухабист, надо шлифовать его дальше, перед тем, как показывать нормальным людям
Re: Тюринг-полные ли шаблоны C++?
От: TimurSPB Интернет  
Дата: 13.02.12 21:42
Оценка:
Да, тьюринг-полные.
Но для решения практических задач это бесполезное знание.
Make flame.politics Great Again!
Re[23]: Тюринг-полные ли шаблоны C++?
От: VladD2 Российская Империя www.nemerle.org
Дата: 14.02.12 14:23
Оценка:
Здравствуйте, m e, Вы писали:

ME>я слегка пошлифовал твой текст, но даже и в моей редакции он порядком ухабист, надо шлифовать его дальше, перед тем, как показывать нормальным людям


По шлифовал что и где?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[24]: Тюринг-полные ли шаблоны C++?
От: m e  
Дата: 14.02.12 14:38
Оценка:
VD>По шлифовал что и где?

что -- начало http://www.rsdn.ru/article/nemerle/MacrosExtCoursePart4.xml
Автор(ы): Владислав Юрьевич Чистяков
Дата: 03.09.2009
В данной части статьи рассказывается о том, как работает система вывода типов Nemerle, о том, как с ней могут взаимодействовать макросы Nemerle, и что это дает
плюс добавил туда чуть-чуть из твоей 5-й части

в первую очередь, давай выясним не ошибся ли я и правильно ли все понял

в частности, удаленная мной фаза (см. в тексте) действительно является пересказом соседней, или я не разобрался?

вообще предполагается, ты что мой текст прочтешь и укажешь ошибки или ложные мнения, которые в результате его чтения могут возникнуть

если интересно почему я считаю, что это шлифовка, то тоже могу написать, но объем будет примерно как у самого текста

вкратце: фазы компиляции *нельзя* именовать цифрами, да еще написанными не от руки, а полученными через нумерованный список (и если у фаз есть общепринятые названия, отличные от моих, то их надо указать)
Re[23]: Тюринг-полные ли шаблоны C++?
От: VladD2 Российская Империя www.nemerle.org
Дата: 14.02.12 17:11
Оценка:
Здравствуйте, m e, Вы писали:

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

ME>в скобках подчеркнутым выделены мои вопросы и замечания
ME>какие тут ошибки?

Главных ошибок две
1. Ты вместо того, чтобы прочитать текст дальше взялся за скрупулезный разбор поверхностного введения. За одно почему-то посчитал, что фазы используемые макросах должны иметь четкое отображение на этапы компиляции. Зависимость несоменнно есть, но фазы макросов идут как бы между этапами компиляции.

2. Ты взялся за чтение текста предназначенного для тех кто уже разбирается в макросах и языке и хочет углубить свои знания. Читать "расширенный курс" не зная языка и не имея опыта создания макросов — это не верный шаг. Так ты только запутаешься.

ME>для начала назовем агрегатами (aggregates) все, что может иметь члены (полный список должен быть в описании языка); агрегаты могут поддерживать наследование (или всегда поддерживают наследование?)


Не. Так мы делать не будем. Это какая-то самодеятельность. Вся терминалогия и описания того как классифицируются типы в Немерле описана в 6-й части Языка Немерле
Автор(ы): Чистяков Владислав Юрьевич
Дата: 20.02.2012
Данная часть посвящена синтаксису Nemerle.
. Там все подробно разжевано. Типы делятся (в том числе) на определяемые пользователем и встроенные
Автор(ы): Чистяков Владислав Юрьевич
Дата: 20.02.2012
Данная часть посвящена синтаксису Nemerle.
.

Наследование поддерживается только в классах, интерфейсах и от части в структурах и перечислениях. При этом есть масса нюансов. Полностью наследование доступно только для классов и интерфейсов.

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

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

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

ME>Фаза импорта. Считывается описание типов, импортируемых из внешних сборок.


ME>Фаза пре-парсинга. Производится пре-парсинг файлов, получая при этом дерево токенов, свернутых по скобкам (че такое скобки? я догадываюсь, но не ясно зачем это надо -- у вас ассоциативность оператора может зависеть от типов, или зачем?).


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

ME> На этом этапе формируется так называемое «окружение»(где жаргонный термин?).


Не понял вопроса. Далее же объясняется, что такое окружение.

ME>В окружении сохраняется информация об открытых пространствах имен, а значит, доступных макросах и операторах.


ME>Фаза парсинга. Производит парсинг. Он состоит из создания AST верхнего уровня (TopDeclaration) (нет четкого примера в описании синтаксиса;


Подразумевается, что человек читающий эту статью, должен уже знать такие вещи. Читй 6-ю часть "Язык Немерле" или доки по синтаксису на сайте.

ME>Фаза перед наследованием. Запуск макросов BeforeInheritance.


Тут верно, только не "макросов BeforeInheritance", а макросов (можно даже сказать макросов верхнего уровня) работающих на фазе BeforeInheritance. Именно по этому не надо называть фазами еще что-то.

ME>Фаза наследования. Строится дерево наследования агрегатов. Дерево строится на основании информации об импортированных из других сборок агрегатов и на основании TopDeclaration разобранных исходных файлов.


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

ME>[u](выброшеная фаза: Производит разрешение наследования (задает отношения между типами), т.к. она излишняя)


Зря. Это как раз правильная фраза. Как я уже говорил это поверхностное описание. Здесь полноты и не требовалось. Цели другие.

ME>Фаза перед типизацией членов. Запуск макросов BeforeTypedMembers.


Ага. Фаза макросов BeforeTypedMembers. Ну, да про фазы повторяться не буду.

ME>Фаза типизации членов. Типизируются члены агрегатов,


Традиционно "агрегатов" в топку. Можно было бы написать "пользовательских типов определенных в проекте", но опять таки для этой статьи — это какой-то оверкил в области разжевывание очевидных для целевой аудитории вещей.

ME>т.е. связываются текстовые (че??? у нас же вроде AST везде?)


В AST имена в текстовой форме и лежат. Как им еще можно лежать то?

ME>описания типов параметров и возвращаемых значений с типами из дерева агрегатов. Компилятор не допускает вывода типов для членов агрегатов, поэтому после этого этапа становятся известными типы всех членов.


ME>Для методов это означает, что становятся известны типы аргументов и типы возвращаемых значений.


Масло масляное.

ME>Фаза типизации тел методов. (К методам относятся и конструкторы). Инициализаторы полей, а также getter-ы/setter-ы свойств преобразуются в методы (так, инициализаторы полей реально копируются в конструкторы агрегатов).


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

ME>Затем типизируются тела методов в агрегатах --


Традиционно агрегаты в топку

ME>раскрываются макросы WithTypedMembers и производится вывод типов.


Нет. Макрос работающие на фазе WithTypedMembers отрабатывают до начала типизации тел членов. Опять же читае 5-ю часть "Язык Немерле", где это хорошо расписано. Все фазы относятся к макросам верхнего уровня. Макросы раскрываемые при типизации тел относятся к макросам уровня выражений.

ME>Это самая сложная фаза компиляции. На выходе этой фазы тела методов содержат типизированный AST (TExpr). Состоит из следующих подфаз:


ME>

Опять же, если бы ты прочел что написано дальше, то понял бы, что это очень поверхностное описание. Далее в статье было дано более глубокое и более точное описание:

Типизация осуществляется объектом Typer (из пространства имен Nemerle.Compiler). Он читает каждое выражение (осмысленное сочетание веток AST) нетипизированного AST – PExpr. Проверяет, не совпадает ли выражение с шаблоном, описанным в одном из макросов уровня выражения (который «виден» в данной области видимости). Если выявляется совпадение, то выражение передается на обработку этому макросу. Перед передачей выражения макросу типизатор производит декомпозицию выражения в соответствии с шаблоном, описанным в макросе. При этом выражение может быть разбито на подвыражения для соответствия параметрам макроса.
...

и далее по тексту.

Основная мысль заключается в том, что макросы раскрываются во время типизации, но до типизации непосредственно конкретного выражения которое поражается макросом. Кроме того макрос возвращает выражения в которых так же могут встречаться макросы. Типизатор разбирает результирующее выражение (которое возвратил макрос) и типизироует его по путно раскрывая те макросы которые есть в нем. Результатом работы типизатор всегда является TExpr. В TExpr макросов уже быть не может. Зато в нем есть типы и разрешенные имена. Однако типы могут быть не вывденными, а подветки TExpr могут содержать объект отложенной типизации.

Эта статья
Автор(ы): Владислав Юрьевич Чистяков
Дата: 03.09.2009
В данной части статьи рассказывается о том, как работает система вывода типов Nemerle, о том, как с ней могут взаимодействовать макросы Nemerle, и что это дает
как раз и рассказывает о типах и объектах отложенной типизации, а не является описанием чего-бы то ни было другого (языка в частности).

ME>Фаза оптимизации. Производятся различные преобразования над типизированым AST, оптимизация и т.п. (что и т.п.?)


Там много чего делается. Это не важно в контексте статьи. Например, проверяется достижим ли код и выдаются предупреждения о его недостижимости.

ME>Фаза генерации. Производится генерация IL.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[25]: Тюринг-полные ли шаблоны C++?
От: VladD2 Российская Империя www.nemerle.org
Дата: 14.02.12 17:28
Оценка:
Здравствуйте, m e, Вы писали:

VD>>По шлифовал что и где?


ME>что -- начало http://www.rsdn.ru/article/nemerle/MacrosExtCoursePart4.xml
Автор(ы): Владислав Юрьевич Чистяков
Дата: 03.09.2009
В данной части статьи рассказывается о том, как работает система вывода типов Nemerle, о том, как с ней могут взаимодействовать макросы Nemerle, и что это дает
плюс добавил туда чуть-чуть из твоей 5-й части


Если ты об этом
Автор: m e
Дата: 14.02.12
своем сообщении, то ты скорее запутал, чем что-то разжевал. Я тебе там дал подробный ответ. Хотя, откровенно говоря, не вижу смысла вообще это обсуждать. Ты просто взялся не за ту статью и начал разбирать в ней не существенные детали (вводную).

ME>в первую очередь, давай выясним не ошибся ли я и правильно ли все понял


Ошибся и не раз. Подробности здесь
Автор: VladD2
Дата: 14.02.12
.

ME>в частности, удаленная мной фаза (см. в тексте) действительно является пересказом соседней, или я не разобрался?


Это какая? Вообще, я не понимаю зачем ты всем этим занялся.

ME>если интересно почему я считаю, что это шлифовка, то тоже могу написать, но объем будет примерно как у самого текста


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

ME>вкратце: фазы компиляции *нельзя* именовать цифрами, да еще написанными не от руки, а полученными через нумерованный список (и если у фаз есть общепринятые названия, отличные от моих, то их надо указать)


Все что я мог ответить, я ответил здесь
Автор: VladD2
Дата: 14.02.12
(в частности и про фазы).
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[26]: Тюринг-полные ли шаблоны C++?
От: m e  
Дата: 14.02.12 17:57
Оценка:
VD>Я вообще не понимаю смысла твоих действий. Не надо быть провидцем, чтобы предсказать, что из затеи твоей ничего хорошего не получится. Ведь ты пока что не в теме того что пытаешь шлифовать.

не надо быть поваром, чтобы понять, что блюдо подгорело

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

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


собственно, я и не собираюсь чтобы из моей затеи что-то "получилось" в твоем понимании — мне достаточно, чтобы я имел у себя описание немерле, соответствующее действительности, и написанное тем языком, который я считаю подходящим для спецификации, а не охами-вздохами "ай как это сложно" (можешь посчитать охи в 4-й части)

можно, конечно, попросить вашу команду написать описание немерле 1 на человеческом языке, но я подозреваю, что это не будет сделано -- вы скорее будете заниматься немерле 2 (кстати, по нему я тоже потом задам вопросы)

VD> А текст этот рассчитан на тех кто в теме и ни разу не претендует на описание языка или даже компилятора. Это просто вводная для темы типизации в макросах.


в эн+1 раз спрашиваю: а где описание немерле 1?

кстати, 6-я часть опять описывает скорее парсер, чем синтаксис!

мне видимо опять-таки придется для себя из нее сделать выжимку, с моей точки зрения подходящую под описание языка, и задать вопросы

да, я бы тебе эти так беспокоящие тебя выжимки не показывал, но, похоже, это единственный способ выяснить, где я понял что-то неверно
Re[24]: Тюринг-полные ли шаблоны C++?
От: m e  
Дата: 14.02.12 18:49
Оценка:
VD> За одно почему-то посчитал, что фазы используемые макросах должны иметь четкое отображение на этапы компиляции. Зависимость несоменнно есть, но фазы макросов идут как бы между этапами компиляции.

вот и хорошо

осталось заменить слова "как бы" на более точные (или выбросить вообще?)

VD>2. Ты взялся за чтение текста предназначенного для тех кто уже разбирается в макросах и языке и хочет углубить свои знания. Читать "расширенный курс" не зная языка и не имея опыта создания макросов — это не верный шаг. Так ты только запутаешься.


ровно наоборот -- создавать макросы, не имея общей картины -- это признак code monkey

пожалуста перестань мне советовать стать code monkey -- это бесполезно

ME>>для начала назовем агрегатами


VD>Не. Так мы делать не будем. Это какая-то самодеятельность.


не делайте -- оно сделано для того, чтобы мне было легче выяснить, что спрашивать о немерле (впрочем, будь я дизайнером языка, я бы ввел это понятие)

VD>Наследование поддерживается только в классах, интерфейсах и от части в структурах и перечислениях. При этом есть масса нюансов. Полностью наследование доступно только для классов и интерфейсов.


а есть ли члены в чем-то, кроме как в классах, интерфейсах, в структурах? в перечислениях скажем?

VD>Первое что хочется заметить — оригинальный список является поверх и от того не вполне корректным. В нем намеренно были сделаны не некоторые вольные допущения. Если уж хочется разобраться глубже, то придется их устранить.


ок

VD>Второе замечание — использования термина "фаза" здесь не уместно, так как оно входит в конфликт с термином используемым для обозначения фазы работы макросов (которая так же иногда называется фазой компиляции). Наверно имеет смыл по моим текстам поправить "фазы компиляции" на "фазы работы макросов".


ммм... у вас макросы -- это части компилятора; почему нельзя отвести часть фаз компиляции под части работы макросов?

VD>Это детали не относящиеся к делу. Если вкратце, сворачивание по скобкам обходит несовершенство парсер используемого в Немерле 1.х. Этот шаг решат ряд проблем от поддержки синтаксиса основанного на отступах, до формирования тех самых окружений хранящих информацию об открытых синтаксических окружениях.


что такое скобки? это "(){}[]" или есть еще какие? почему это названо несовершенством?

ME>>Он состоит из создания AST верхнего уровня (TopDeclaration) (нет четкого примера в описании синтаксиса;


VD>Подразумевается, что человек читающий эту статью, должен уже знать такие вещи. Читй 6-ю часть "Язык Немерле" или доки по синтаксису на сайте.


и где в 6-й части дано *определение* TopDeclaration? там такого слова вообще нет

VD> или доки по синтаксису на сайте.


я уже догадался по смыслу


ME>>Фаза типизации членов. Типизируются члены агрегатов,


VD>Традиционно "агрегатов" в топку. Можно было бы написать "пользовательских типов определенных в проекте", но опять таки для этой статьи — это какой-то оверкил в области разжевывание очевидных для целевой аудитории вещей.


делагат является пользовательским типом; есть ли у него члены? типизируются ли члены делегатов на этой фазе?

ME>>т.е. связываются текстовые (че??? у нас же вроде AST везде?)


VD>В AST имена в текстовой форме и лежат. Как им еще можно лежать то?


ex4> Типизирует члены типов, т.е. связывает текстовые описания типов параметров и возвращаемых значений с типами из дерева типов.


"текстовые описания типов параметров" -- описания это не имена

или у вас описание типов параметров может состоять только из имени? и не-имена List[T] (или если пофантазировать List[T+U+V-W]) в качестве описание типов параметров недоступны? или все еще они неразобраны (т.е. в тексте)?

ME>>Для методов это означает, что становятся известны типы аргументов и типы возвращаемых значений.


VD>Масло масляное.


гыгы

это я перенес твое "типы аргументов и возвращаемых значений известны перед началом процесса типизации" в то место, где оно должно было бы стоять, и чуть изменил формулировку

ME>>Фаза типизации тел методов. (К методам относятся и конструкторы). Инициализаторы полей, а также getter-ы/setter-ы свойств преобразуются в методы (так, инициализаторы полей реально копируются в конструкторы агрегатов).


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


ясно

ME>>раскрываются макросы WithTypedMembers и производится вывод типов.


VD>Нет. Макрос работающие на фазе WithTypedMembers отрабатывают до начала типизации тел членов. Опять же читае 5-ю часть "Язык Немерле", где это хорошо расписано. Все фазы относятся к макросам верхнего уровня. Макросы раскрываемые при типизации тел относятся к макросам уровня выражений.


почти ясно

а на какой фазе (между какими фазами) работают макросы уровня выражений?

ME>>Это самая сложная фаза компиляции. На выходе этой фазы тела методов содержат типизированный AST (TExpr). Состоит из следующих подфаз:



VD>Опять же, если бы ты прочел что написано дальше, то понял бы, что это очень поверхностное описание. Далее в статье было дано более глубокое и более точное описание:

VD>[q]
VD>Типизация осуществляется объектом Typer (из пространства имен Nemerle.Compiler)

естественно я это прочитал, но это относится к деталям реализации

VD>Основная мысль заключается в том, что макросы раскрываются во время типизации, но до типизации непосредственно конкретного выражения которое поражается макросом. Кроме того макрос возвращает выражения в которых так же могут встречаться макросы. Типизатор разбирает результирующее выражение (которое возвратил макрос) и типизироует его по путно раскрывая те макросы которые есть в нем. Результатом работы типизатор всегда является TExpr. В TExpr макросов уже быть не может. Зато в нем есть типы и разрешенные имена. Однако типы могут быть не вывденными, а подветки TExpr могут содержать объект отложенной типизации.


так, это я обдумаю




насчет агрегатов -- хотя язык и не мой, но я могу (и буду) вводить свою терминологию для его описания; я, естественно, постараюсь излишне не перегружать всех вас этой самопальной терминологией, но использовать ее скорее всего продолжу, т.к. она позволяет мне лучше задавать вопросы
Re[27]: Тюринг-полные ли шаблоны C++?
От: VladD2 Российская Империя www.nemerle.org
Дата: 14.02.12 18:55
Оценка:
Здравствуйте, m e, Вы писали:

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


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

ME>собственно, я и не собираюсь чтобы из моей затеи что-то "получилось" в твоем понимании — мне достаточно, чтобы я имел у себя описание немерле, соответствующее действительности, и написанное тем языком, который я считаю подходящим для спецификации, а не охами-вздохами "ай как это сложно" (можешь посчитать охи в 4-й части)


ME>можно, конечно, попросить вашу команду написать описание немерле 1 на человеческом языке, но я подозреваю, что это не будет сделано -- вы скорее будете заниматься немерле 2 (кстати, по нему я тоже потом задам вопросы)


Думаю, что тут основная проблема в том, что ты под "человеческим" понимаешь что-то отличное от того, что под этим понимают остальные. По сему угодить тебе трудно. Да и нет задачи огождать отдельным людям.

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

VD>> А текст этот рассчитан на тех кто в теме и ни разу не претендует на описание языка или даже компилятора. Это просто вводная для темы типизации в макросах.


ME>в эн+1 раз спрашиваю: а где описание немерле 1?


В 6-й и 7-й части (которая появится вскоре). Так же на сайте в разделе Reference Manual.

ME>кстати, 6-я часть опять описывает скорее парсер, чем синтаксис!


Это явно высосанное из пальца утверждение. В прочем, с интересом послушаю, что в твоем понимании является синтаксисом. И чем не удовлетворяет синтаксис описанный в EBNF/PEG.

ME>мне видимо опять-таки придется для себя из нее сделать выжимку, с моей точки зрения подходящую под описание языка, и задать вопросы


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

ME>да, я бы тебе эти так беспокоящие тебя выжимки не показывал, но, похоже, это единственный способ выяснить, где я понял что-то неверно


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

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

В прочем, еще раз повторюсь, что без практики все равно язык не изучить. У языка есть только одно точное описание — его компилятор. По понятным причинам полностью вместить в могз его невозможно. По сему любые стандарты, спецификации или вольные рассказы — это всего лишь абстрактные описания приближающиеся к описанию языка не более чем учебники истории к описанию реальной жизни.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[28]: Тюринг-полные ли шаблоны C++?
От: m e  
Дата: 14.02.12 19:07
Оценка:
VD>Думаю, что тут основная проблема в том, что ты под "человеческим" понимаешь что-то отличное от того, что под этим понимают остальные. По сему угодить тебе трудно. Да и нет задачи огождать отдельным людям.

конечно, на отдельных людей нет смысла заморачиваться

однако есть такое понятие как целевая аудитория

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

да, никто не спорит, что показать интеграцию с VS необходимо и полезно, но упор, мне кажется надо делать на тех, кто знает, что им надо -- так как те, кто не знают, спокойно пишут себе на шарпе (а то и на РНР) и не ищут чего-то иного
Re[28]: Тюринг-полные ли шаблоны C++?
От: m e  
Дата: 14.02.12 19:09
Оценка:
VD>Так может вместо этой самодеятельности приводить цитаты из текста и просить объяснить непонятные моменты? А я уж на основании этого подумаю, что и как поправить, чтобы подобных вопросов не возникало.

эта самодеятельность -- почти всегда немного измененные (в соответствии с моим пониманием) цитаты из твоего текста
Re[28]: Тюринг-полные ли шаблоны C++?
От: m e  
Дата: 14.02.12 19:15
Оценка:
VD>Разумные замечания, вроде уточнения терминологии или префразирования неоднозначных раз учтем.

да, уточнить было бы весьма полезно -- скажем, сделать глоссарий-и-одновременно-определение-части-понятий, удалить дубликаты, почисть *языковую* терминологию от названий классов в компиляторе

VD> Но переименовывать номера в фазы


пусть стадии, не важно -- главное не номера

VD> или называть контейнерами определяемые пользователями типы явно неконструктивно.


агрегаты это, а не контейнеры

кстати -- энумы это определяемые пользователями типы, но есть ли у них члены, которые типизируются на фазе Х? а?
Re[28]: Тюринг-полные ли шаблоны C++?
От: m e  
Дата: 14.02.12 19:20
Оценка:
кстати я не утверждаю, что aggregates здесь наиболее подхоящий термин -- можете придумать свой (и я его буду использовать), но точно не контейнер
Re[25]: Тюринг-полные ли шаблоны C++?
От: VladD2 Российская Империя www.nemerle.org
Дата: 14.02.12 19:45
Оценка:
Здравствуйте, m e, Вы писали:

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


ME>вот и хорошо

ME>осталось заменить слова "как бы" на более точные (или выбросить вообще?)

Можешь выбросить.

VD>>2. Ты взялся за чтение текста предназначенного для тех кто уже разбирается в макросах и языке и хочет углубить свои знания. Читать "расширенный курс" не зная языка и не имея опыта создания макросов — это не верный шаг. Так ты только запутаешься.


ME>ровно наоборот -- создавать макросы, не имея общей картины -- это признак code monkey


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

ME>пожалуста перестань мне советовать стать code monkey -- это бесполезно


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

ME>>>для начала назовем агрегатами


VD>>Не. Так мы делать не будем. Это какая-то самодеятельность.


ME>не делайте -- оно сделано для того, чтобы мне было легче выяснить, что спрашивать о немерле (впрочем, будь я дизайнером языка, я бы ввел это понятие)


Ну, так просто изучи терминологию. 5-я и 6-я часть дает ее достатке. А если каждый будет вводить свои понятия и общаться с их применением, то никого понять будет нельзя.

VD>>Наследование поддерживается только в классах, интерфейсах и от части в структурах и перечислениях. При этом есть масса нюансов. Полностью наследование доступно только для классов и интерфейсов.


ME>а есть ли члены в чем-то, кроме как в классах, интерфейсах, в структурах? в перечислениях скажем?


Естественно. Фактически члены есть у всех типов. Все типы виртуально наследуются от типа object. По сему такие методы как GetType() или ToString() есть у экземпляров всех типов. Кроме того есть разные хэлпер-типы вроде System.Enum и т.п. Но все это относится не к немерлу как языку, а к донтету, как к рантайму и базовой платформе. Посему их описание нет смысла включат в язык. Их описания доступны на MSDN .

Используя немерл нужно быть знакомым с дотентом в той или иной степени. Конечно изучать язык можно и не вадаваясь в дотнет, но эффективно его использовать без дотенат не получится.

Более того, во многом семантика немерла близка к семантике шарпа. Так что зная шарп изучить немерл очень просто.

ME>ммм... у вас макросы -- это части компилятора; почему нельзя отвести часть фаз компиляции под части работы макросов?


Потому что для создания макросов нет нужды забивать голову деталями работы компилятора. Макрос работает с компилятор через определенные интерфейсы. И только их и нужно описывать (по крайней мере в описании языка). Иначе объем информации будет слишком велик для программиста (пользователя языка).

Для использования макросов достаточно знать о фазах когда они работают. Их 3 для макросов верхнего уровня и для макросов уровня выражений. Можно считать ее 4-й стадией идущей после трех предыдущих, но все же она относится к макросам другого вида.

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

ME>что такое скобки? это "(){}[]" или есть еще какие? почему это названо несовершенством?


Да — они. Плюс еще <[ ]> используется для квази-цитат. Это описано в одной из частей расширенного курса, если не ошибаюсь и должно появиться в 7-й части.

ME>и где в 6-й части дано *определение* TopDeclaration? там такого слова вообще нет


Да
Автор(ы): Чистяков Владислав Юрьевич
Дата: 20.02.2012
Данная часть посвящена синтаксису Nemerle.


VD>> или доки по синтаксису на сайте.


ME>я уже догадался по смыслу


Мне тоже кажется, что название говорит само за себя .

ME>делагат является пользовательским типом;


Я же уже давал ссылку на классификацию
Автор(ы): Чистяков Владислав Юрьевич
Дата: 20.02.2012
Данная часть посвящена синтаксису Nemerle.
.
Делегат — это определяемый пользователем тип.

ME>есть ли у него члены?


Есть, но в основном встроенные, унаследованные от System.Delegate. Плюс компилятор генерирует такие члены как Invoke. Все что связано с делегатами является одинаковым для всех языков дотнета поддерживающих их. Так что если нужны детали, то можно читать любой материла по C# или делегатам в дотнете (включая спецификация CLI).

ME>типизируются ли члены делегатов на этой фазе?


Да, те что генерируются компилятором.

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

ME>"текстовые описания типов параметров" -- описания это не имена


ОК, подумаю как переформулировать, чтобы звучало по лучше.

ME>или у вас описание типов параметров может состоять только из имени? и не-имена List[T] (или если пофантазировать List[T+U+V-W]) в качестве описание типов параметров недоступны? или все еще они неразобраны (т.е. в тексте)?


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

ME>>>Для методов это означает, что становятся известны типы аргументов и типы возвращаемых значений.


VD>>Масло масляное.

ME>гыгы

ME>это я перенес твое "типы аргументов и возвращаемых значений известны перед началом процесса типизации" в то место, где оно должно было бы стоять, и чуть изменил формулировку


Это какой-то jpeg-перенос. С потерей смысла.

ME>>>раскрываются макросы WithTypedMembers и производится вывод типов.


VD>>Нет. Макрос работающие на фазе WithTypedMembers отрабатывают до начала типизации тел членов. Опять же читае 5-ю часть "Язык Немерле", где это хорошо расписано. Все фазы относятся к макросам верхнего уровня. Макросы раскрываемые при типизации тел относятся к макросам уровня выражений.


ME>почти ясно


А что не ясно?

ME>а на какой фазе (между какими фазами) работают макросы уровня выражений?


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

Это так же описано в 5-й части и разжевано до неприличия.

VD>>Опять же, если бы ты прочел что написано дальше, то понял бы, что это очень поверхностное описание. Далее в статье было дано более глубокое и более точное описание:

VD>>[q]
VD>>Типизация осуществляется объектом Typer (из пространства имен Nemerle.Compiler)

ME>естественно я это прочитал, но это относится к деталям реализации


Забавный у тебя взгляд на вещи. То тебе нужны детали, то это уже детали реализации. Еще раз повторюсь, все детали языков доступны только в исходниках их компиляторов. Более того, язык имеющий несоклько компиляторов по факту имеет несколько диалектов. Ну, а любое описание языка — это приближение с некоторой детализацией. Описание из 4-й части расширенного курса, идущее в него начале — это очень поверхностное описание цель которого дать очень общее представление. Открою секрет — формально оно во многом некорректно.

VD>>Основная мысль заключается в том, что макросы раскрываются во время типизации, но до типизации непосредственно конкретного выражения которое поражается макросом. Кроме того макрос возвращает выражения в которых так же могут встречаться макросы. Типизатор разбирает результирующее выражение (которое возвратил макрос) и типизироует его по путно раскрывая те макросы которые есть в нем. Результатом работы типизатор всегда является TExpr. В TExpr макросов уже быть не может. Зато в нем есть типы и разрешенные имена. Однако типы могут быть не вывденными, а подветки TExpr могут содержать объект отложенной типизации.


ME>так, это я обдумаю


Это, кстати, чуть ли не важнейшая ведь которую нужно понять о макросах уровня выражения.

ME>


ME>насчет агрегатов -- хотя язык и не мой, но я могу (и буду) вводить свою терминологию для его описания;


Не стоит. Это явно тупиковый путь. Терминология должна быть одна.

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


Вопросы еще нужно понимать. И если, скажем я уже настроил в своей голове отображение между принятой терминалогией и твоей, то кто-то другой тебя просто не поймет. Мы ведь не в личной переписке общаемся...

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

Есть более точное понятие — определяемые пользователем типы. Их можно так же называть: декларируемые типы или пользовательские типы. Им противопоставляются встроенные типы (предопределенные). Суть их различия в том, что встроенные типы заранее предопределены. Пользовательские же типы являются позволяют декларировать новые, конкретные, типы.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[26]: Тюринг-полные ли шаблоны C++?
От: m e  
Дата: 14.02.12 21:46
Оценка:
VD>Потому что для создания макросов нет нужды забивать голову деталями работы компилятора. Макрос работает с компилятор через определенные интерфейсы. И только их и нужно описывать (по крайней мере в описании языка). Иначе объем информации будет слишком велик для программиста (пользователя языка).

фазы (или стадии) это не детали работы компилятора, епрст, это то, без чего я не сяду писать макрос, и предложения написать макрос без такого знания -- это предложение стать code monkey

я это сказал последний раз

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

VD>В Н2, возможно стадии исчезнут. Вместо этого будет использоваться реактивная модель. Но это уже уход от темы.


не уход, а интересный поворот

ладно, потом отвечу на все остальное
Re[28]: Тюринг-полные ли шаблоны C++?
От: m e  
Дата: 16.02.12 17:40
Оценка:
ME>>кстати, 6-я часть опять описывает скорее парсер, чем синтаксис!
VD>Это явно высосанное из пальца утверждение. В прочем, с интересом послушаю, что в твоем понимании является синтаксисом.

разница между синтаксисом и парсером примерно как между задачей и решением

впрочем, это мелкая претензия -- забей

дальше, на место агрегатов в свое описание я поставлю пользовательские типы -- ты меня убедил

теперь насчет ошибок в описании -- есть ли мне смысл изучать 4-ю часть дальше -- причем именно для понимания фаз, и не надо пожалуста мне советовать что-то попроще, или стоит подождать новое, более точное описание?
Re[2]: Тюринг-полные ли шаблоны C++?
От: jazzer Россия Skype: enerjazzer
Дата: 16.02.12 17:48
Оценка:
Здравствуйте, TimurSPB, Вы писали:

TSP>Да, тьюринг-полные.

TSP>Но для решения практических задач это бесполезное знание.

Даже вредное
Ибо у огорошенного этим знанием сразу появляется искушение вообще все запихать в шаблоны, раз уж они Тьюринг-полны
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[29]: Тюринг-полные ли шаблоны C++?
От: VladD2 Российская Империя www.nemerle.org
Дата: 16.02.12 17:54
Оценка:
Здравствуйте, m e, Вы писали:

ME>дальше, на место агрегатов в свое описание я поставлю пользовательские типы -- ты меня убедил


ME>теперь насчет ошибок в описании -- есть ли мне смысл изучать 4-ю часть дальше -- причем именно для понимания фаз, и не надо пожалуста мне советовать что-то попроще, или стоит подождать новое, более точное описание?


Смысла нет никакого. 4-я часть расширенного курса посвящена типизации внутри макросов уровня выражения. Так что фаз макросов она не затрагивает.

Фазы описаны в 5-й части Язык Nemerle
Автор(ы): Чистяков Владислав Юрьевич
Дата: 22.09.2011
Данная часть посвящена макросам Nemerle.
.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[26]: фазы компиляции немерле
От: m e  
Дата: 16.02.12 17:57
Оценка:
VD>Более того, во многом семантика немерла близка к семантике шарпа. Так что зная шарп изучить немерл очень просто.

на шарпе я не писал, но основные его отличия от явы знаю, хотя и кое-какие не знаю

скажем, я так полагал что специализация дженериков под типы-значения происходит компилятором шарпа, а не где-то ниже, на уровне IL или рантайма

ME>> TopDeclaration

VD>Мне тоже кажется, что название говорит само за себя .

наоборот -- я *название* долго не понимал (должно быть TopLevelDeclaration), и понял только исходя из анализа логики работы фаз

VD>Добавить свои члены в делегат нельзя. Но можно добавить методы расширения (статические методы которые можно вызвать как экзеплярные, через точку).


полиморфизм методов расширения в немерле разрешается статически? (в дотнете вроде же статически?)

VD> Если же говорить о деталях, то там еще цвета, окружения и много чего прочего есть.


что это такое? (только в *самых* общих чертах)

ME>>>>Для методов это означает, что становятся известны типы аргументов и типы возвращаемых значений.

VD>>>Масло масляное.
ME>>это я перенес твое "типы аргументов и возвращаемых значений известны перед началом процесса типизации" в то место, где оно должно было бы стоять, и чуть изменил формулировку
VD>Это какой-то jpeg-перенос. С потерей смысла.

фазы надо описывать по шаблону:

1. название фазы
2. описание работы
3. постусловие фазы, например "все члены пользовательских классов полностью типизированы"
4. можно чуть добавить масляного масла, но по вкусу


VD>>>Типизация осуществляется объектом Typer (из пространства имен Nemerle.Compiler)

ME>>естественно я это прочитал, но это относится к деталям реализации
VD>Забавный у тебя взгляд на вещи. То тебе нужны детали, то это уже детали реализации.

как я понял, уравнения типизации составляются только после полного раскрытия макросов, так?

тогда для понимания работы макросистемы способ вывода типов не имеет значения

(с ним я буду разбираться отдельно, да там и paper вроде есть)
Re[28]: Тюринг-полные ли шаблоны C++?
От: m e  
Дата: 16.02.12 21:39
Оценка:
вопросы и замечания по http://www.rsdn.ru/article/nemerle/Nemerle-macros-intro.rsdnml.xml
Автор(ы): Чистяков Владислав Юрьевич
Дата: 22.09.2011
Данная часть посвящена макросам Nemerle.


>Макросы верхнего уровня могут применяться на уровне:

>сборки (Assembly level);
>типа;
>члена (метода, свойства, поля, события);
>параметра.

>Макросы верхнего уровня выполняются в момент, когда компилятор обрабатывает конструкции верхнего уровня целевой программы, такие как:

>атрибуты уровня сборки;
>типы;
>члены типов;
>параметры членов типов

эти два списка обозначают одно и то же, или разное?

в любом из этих случаев, наличие двух похожих, но текстуально (или даже по-смысловому) разных сущностей существенно затрудняет обучение — т.к. обучающемуся первоначально приходится держать в уме в значительной степени не смысл, а текст!

кстати, похоже это повсеместно во введениях -- и в частности это я имел в виду, когда жаловался на стиль изложения

(а не стоит ли мне постить такие вопросы в раздел "немерле"?)

заодно:

параметры членов типов это на самом деле параметры методов (аргументы методов)?
Re[28]: Тюринг-полные ли шаблоны C++?
От: m e  
Дата: 16.02.12 21:56
Оценка:
словарик, он же глоссарий для немерле -- есть где-то такой?

какой я буду делать для себя (копипастом в основном) в порядке изучения:

стиль определений -- русское название, анлгийское название, жаргонное название (вроде PExpr), короткое объяснение, примеры, ссылка на подробные объяснения

для ссылки, кстати, необходимо назвать вводные курсы кратко, скажем http://www.rsdn.ru/article/nemerle/MacrosExtCoursePart4.xml
Автор(ы): Владислав Юрьевич Чистяков
Дата: 03.09.2009
В данной части статьи рассказывается о том, как работает система вывода типов Nemerle, о том, как с ней могут взаимодействовать макросы Nemerle, и что это дает
это М4 (макросы-4, M4), а http://www.rsdn.ru/article/nemerle/Nemerle-macros-intro.rsdnml.xml
Автор(ы): Чистяков Владислав Юрьевич
Дата: 22.09.2011
Данная часть посвящена макросам Nemerle.
это Я5 (язык-5, L5)

соответственно реквестирую разумный набор этих самых кратких названий (всякие там интервью с... понятно не нужны)
Re[27]: фазы компиляции немерле
От: VladD2 Российская Империя www.nemerle.org
Дата: 16.02.12 23:53
Оценка:
Здравствуйте, m e, Вы писали:

ME>на шарпе я не писал, но основные его отличия от явы знаю, хотя и кое-какие не знаю


Отличий знать мало. Тем более, что их куда больше, чем ты себе представляешь. Многие твои вопросы — это вопросы не по языку, а по дотнету. И они подробно описаны много раз. Потому в описании языка на них и нет ответов.

ME>скажем, я так полагал что специализация дженериков под типы-значения происходит компилятором шарпа, а не где-то ниже, на уровне IL или рантайма


Это не верное представление. Дотнет поддерживает дженерики в рантайме. И они порождают специализации для значимых типов в рантайме же. Компилятор может только подставить конекретные типы в параметры типов. А уж остальная магия на совести рантайма.

Это дает как плюсы, так и минуся. Плюс в "компонентости" решений. Можно породить новый тип в рантайме. В рантайме же есть вся метаинформация о типе. Но это же порождает и минуся. Один из них — невозможность вмешаться в ход специализации макросом.

ME>наоборот -- я *название* долго не понимал (должно быть TopLevelDeclaration), и понял только исходя из анализа логики работы фаз


Ну, знаете ли!...

ME>полиморфизм методов расширения в немерле разрешается статически? (в дотнете вроде же статически?)


Если под полиморфизмом понимать перегрузку, то — да. Если аналог виртуальности методов, то для методов расширений виртуальность не поддерживается. Это просто синтаксический сахар, чтобы можно было вызвать метод "через точку".

VD>> Если же говорить о деталях, то там еще цвета, окружения и много чего прочего есть.


ME>что это такое? (только в *самых* общих чертах)


Ох, ох, ох... Это не простая тема. Попробую.

Каждое имя это объект содержащий в себе окружение в котором оно было создано и "цвет" (целочисленный идентификатор контекста в котором оно было создано). Цвета — это часть гигиены макросов. Иначе идентификаторы из макросов пересекались бы с одноименными идентификаторами из других макросов или кода полученного из исходников. При запуске макроса в текущий контекст устанавливается новый цвет. Так что все идентификаторы созданные из квази-цитат (средства формироания кода) получат именно его.

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

ME>фазы надо описывать по шаблону:


ME>1. название фазы

ME>2. описание работы
ME>3. постусловие фазы, например "все члены пользовательских классов полностью типизированы"
ME>4. можно чуть добавить масляного масла, но по вкусу

Примерно так они и описаны в 5-й части Язык Немерле на которую я уже устал давать ссылку.

ME>как я понял, уравнения типизации составляются только после полного раскрытия макросов, так?


Не. И я уже раз 5 это объяснял. Не после, а в процессе. Читается ветка нетипизированного АСТ, проверяется не макрос ли это, если макрос вызвается макрос который должен раскрыться. Результат снова проверяется, если это не макрос, то типизируется. Но типизируется именно отдельная ветка. При этом часть кода уже может быть типизирован, а часть (более глубоко лежащая) — нет.

Так что не после, а в процессе.

Макрос может сам вызвать типизацию и вернуть типизированное АСТ завернутое в специальную ветку. Кроме того, есть объекты отложенной типизации которые могут легко захватывать куски нетипизированного АСТ и делать с ними потом что-то. А это означает, что в типизированном АСТ может находиться ссылка на нетипзированное.

Сюда же еще добавляется многопроходность алгоритма вывода типов Немерле. Так что все становится весьма не просто.

ME>тогда для понимания работы макросистемы способ вывода типов не имеет значения


Для примитивного макроса — да. Но для сложного — нет. Именно этому и была посвящена 4-я часть расширенного курса. А сам курс посвящен написанию сложных макр, которые не отличаются по возможностям от того, что можно впихнуть в компилятор.

ME>(с ним я буду разбираться отдельно, да там и paper вроде есть)


С кем?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[29]: Тюринг-полные ли шаблоны C++?
От: VladD2 Российская Империя www.nemerle.org
Дата: 17.02.12 00:04
Оценка:
Здравствуйте, m e, Вы писали:

ME>вопросы и замечания по http://www.rsdn.ru/article/nemerle/Nemerle-macros-intro.rsdnml.xml
Автор(ы): Чистяков Владислав Юрьевич
Дата: 22.09.2011
Данная часть посвящена макросам Nemerle.


>>Макросы верхнего уровня могут применяться на уровне:

>>сборки (Assembly level);
>>типа;
>>члена (метода, свойства, поля, события);
>>параметра.

>>Макросы верхнего уровня выполняются в момент, когда компилятор обрабатывает конструкции верхнего уровня целевой программы, такие как:

>>атрибуты уровня сборки;
>>типы;
>>члены типов;
>>параметры членов типов

ME>эти два списка обозначают одно и то же, или разное?


Одно — это к чему можно применять макросы, а втрое перечисление того они выполняются. Очевидно, что если макрос применен к типу, то он будет обрабатываться при обработке типа компилятором.

Так что перво "к чему", второе "когда", но они конечно же связаны.

ME>в любом из этих случаев, наличие двух похожих, но текстуально (или даже по-смысловому) разных сущностей существенно затрудняет обучение — т.к. обучающемуся первоначально приходится держать в уме в значительной степени не смысл, а текст!


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

ME>кстати, похоже это повсеместно во введениях -- и в частности это я имел в виду, когда жаловался на стиль изложения


Идеальных тестов не бывает. А процесс их улучшения бесконечный. При этом одному нравится одно, а другому другое.

ME>(а не стоит ли мне постить такие вопросы в раздел "немерле"?)


Стоит.

ME>заодно:

ME>параметры членов типов это на самом деле параметры методов (аргументы методов)?

Члены бывают разные. Например, индексированные свойства тоже имеют параметры, но формально являются свойствами. Привыкай.

Аргументы — это значения. Параметры — формальные описания.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[29]: Тюринг-полные ли шаблоны C++?
От: VladD2 Российская Империя www.nemerle.org
Дата: 17.02.12 00:09
Оценка:
Здравствуйте, m e, Вы писали:

ME>словарик, он же глоссарий для немерле -- есть где-то такой?


Нет. Но, наверно, стоило бы завести.
Если будешь делать, можем потом выложить в вики.

ME>для ссылки, кстати, необходимо назвать вводные курсы кратко, скажем http://www.rsdn.ru/article/nemerle/MacrosExtCoursePart4.xml
Автор(ы): Владислав Юрьевич Чистяков
Дата: 03.09.2009
В данной части статьи рассказывается о том, как работает система вывода типов Nemerle, о том, как с ней могут взаимодействовать макросы Nemerle, и что это дает
это М4 (макросы-4, M4), а http://www.rsdn.ru/article/nemerle/Nemerle-macros-intro.rsdnml.xml
Автор(ы): Чистяков Владислав Юрьевич
Дата: 22.09.2011
Данная часть посвящена макросам Nemerle.
это Я5 (язык-5, L5)


Зачем?

ME>соответственно реквестирую разумный набор этих самых кратких названий (всякие там интервью с... понятно не нужны)


Честно говоря я не вижу в этом смысла.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.