проблема с созданием объекта в макросе
От: _Claus_  
Дата: 29.11.11 16:28
Оценка:
полученное в макросе описание поля

class x   
  REF n : List[x]



расщепляю


 match (e)   
        | <[ $(name : name) : $type ]> => 
          fld_name = name
          fld_type = type
        | _ =>  Message.Error(expr.Location, <#Expected: name : type #>)



и имею в fld_type PExpr.Indexer c типом.

дальше по этому типу хочу создать объект


$refer = $fld_type();


но имею error : cannot find any suitable indexer in 'List' (type is ? -> ?)

попытался воспользоваться


def fld_type_create = MainParser.ParseExpr(typeBuilder.GlobalEnv, $"$(fld_type.ToString())()", false);
//и так пробовал
def fld_type_create = MainParser.ParseExpr(typeBuilder.GlobalEnv, $"$(fld_type.ToString())", false);



и потом использовать в кодоцитате

$refer = $fld_type_create;


но это ничего не меняет. тут видимо что-то глубокое?
Re: проблема с созданием объекта в макросе
От: _Claus_  
Дата: 29.11.11 16:32
Оценка:
описанная ошибка проявляется при генерации кода, компиляция макроса — ok.
Re: проблема с созданием объекта в макросе
От: _nn_ www.nemerleweb.com
Дата: 29.11.11 16:32
Оценка:
Здравствуйте, _Claus_, Вы писали:


_C_>расщепляю



C_>но имею error : cannot find any suitable indexer in 'List' (type is ? -> ?)


Судя по всему просто пропущена точка:
class x   
  REF n : List.[x]


Точка в генерик типе
Автор: _nn_
Дата: 21.09.11
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[2]: проблема с созданием объекта в макросе
От: _Claus_  
Дата: 29.11.11 16:51
Оценка:
C_>>но имею error : cannot find any suitable indexer in 'List' (type is ? -> ?)
__>Судя по всему просто пропущена точка:
с точкой к сожалению вообще труба — компилятор отказывается вызывать макрос — error : Expected: name : type,
а без точки нормально отдает и внутри тип корректно показывает. котовасия только при попытке создания.

  [MacroUsage(MacroPhase.BeforeInheritance, MacroTargets.Method)]\
  macro REF(typeBuilder : TypeBuilder, _ : ClassMember.Function, expr : PExpr)\
  syntax ("REF", expr)
  
    FieldFormer(typeBuilder, expr).proccessREF()
Re[3]: проблема с созданием объекта в макросе
От: _Claus_  
Дата: 29.11.11 17:01
Оценка:
ошибся я — вызывает макрос. валится по другим причинам.
Re: проблема с созданием объекта в макросе
От: VladD2 Российская Империя www.nemerle.org
Дата: 30.11.11 00:26
Оценка:
Здравствуйте, _Claus_, Вы писали:

_C_>полученное в макросе описание поля

_C_>
_C_>  REF n : List[x] 
_C_>


_C_>расщепляю

_C_>
_C_> match (e)   
_C_>        | <[ $(name : name) : $type ]> => 
_C_>          fld_type = type
_C_>

_C_>и имею в fld_type PExpr.Indexer c типом.
_C_>дальше по этому типу хочу создать объект
_C_>
_C_>$refer = $fld_type();
_C_>


Ну, ты лихой товарищ!
Вообще-то никто не гарантирует, что имя типа — это корректное имя его конструктора.

Конкретно в данном случае — _nn_ прав, и у тебя в имени нет точки, а для явного указания параметров типов конструктору точка (к созжалению) нужна.

Но это еще пол беды. Есть куча типов имена конструкторов которых не совпадают с именем типа (или не имеется конструкторов без параметров). Например, твой код по любому обломается на:
* Кортежах.
* Функциях.
* Массивах.
* Списках.
* Да и на обычной строке!

Так что ты явно пошел неверным путем. Нужно придумать что-то другое.

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

Для этого имеет смысл связать тип полученного типа (типизировать его) и анализировать полученный FixedType. Сделать это можно следующим образом:
match (e)   
  | <[ $(name : name) : $type ]> => 
      def typerType = typer.BindFixedType(type);
      match (typerType)
      {
        | Class(typeInfo, typeArgs) =>
          def hasCtor = 
            typeInfo.IsValueType
            || typeInfo.LookupMember(".ctor")
                       .OfType.[IMethod]()
                       .Where(ctor => ctor.Header.Parameters.IsEmpty && ctor.CanAccess(typer.CurrentType))
                       .Any();
          if (hasCtor)
          {
            def typedTypeArgs = typeArgs.Map(tv => <[ $(tv : typed) ]>);
            _ = <[ $(PExpr.FromQualifiedIdentifier(typer.Manager, typeInfo.FullName)).[..$typedTypeArgs](); ]>;
            // ...
          }
          else
            Message.FatalError(type.Location, $"Type '$typeInfo' has no default constructor.");

        // для остальных типов реализуй обработку по необходимости...
        | Array
        | Fun
        | Tuple
        | Tuple
        | Intersection
        | Out
        | Ref
        | StaticTypeVarRef
        | Void => Message.FatalError(type.Location, $"Unsupported type: '$typeInfo'.");
      }


_C_>попытался воспользоваться

_C_>
_C_>def fld_type_create = MainParser.ParseExpr(typeBuilder.GlobalEnv, $"$(fld_type.ToString())()", false);
_C_>//и так пробовал
_C_>def fld_type_create = MainParser.ParseExpr(typeBuilder.GlobalEnv, $"$(fld_type.ToString())", false);
_C_>

_C_>и потом использовать в кодоцитате
_C_>но это ничего не меняет.

Естественно. Это просто бессмысленно. К тебе придет то же выражение.

_C_>тут видимо что-то глубокое?


Ну, да. Путь явно неверный выбран.

Ты что пытаешься изобразить то? Какова логика?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: проблема с созданием объекта в макросе
От: _Claus_  
Дата: 30.11.11 10:20
Оценка:
VD>Ну, ты лихой товарищ!
VD>Вообще-то никто не гарантирует, что имя типа — это корректное имя его конструктора.

Не, там где я это делаю, это динамические контейнеры. Так что усё в порядке, шеф.

VD>Но это еще пол беды. Есть куча типов имена конструкторов которых не совпадают с именем типа (или не имеется конструкторов без параметров). Например, твой код по любому обломается на:

VD>* Кортежах.
VD>* Функциях.
VD>* Массивах.
VD>* Списках.
VD>* Да и на обычной строке!

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

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

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

VD>Так что ты явно пошел неверным путем. Нужно придумать что-то другое.

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

VD>Ты что пытаешься изобразить то? Какова логика?

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

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


def block = <[decl:      
        partial class $name
        {   public static convert_up(datamap: datamap_file, arr: array[exchange_struct], 
              delta:int): IEnumerable[$name]
            /*метод получения множества классов из плоского массива в базе
              delta - смещение мем-блока arr   */ 
            { empty_exchange = exchange_struct();
                            
              size_exchange_struct = memblock.size_type(exchange_struct);
                            
              ...
            }
            //преобразование произвольного IEnumerable[X] в массив его структур для записи в базу
            public static to_array(datamap_:datamap_file, seq: IEnumerable[$name])
            {                
                lst = List();
                ...
            }
            ...


но компилятор много ругается..
и потом добавлю это к классу. тоже вот как добавить?
Re[3]: проблема с созданием объекта в макросе
От: _Claus_  
Дата: 30.11.11 14:00
Оценка:
>>списки N — еще не думал, тоже просто не получится. по любому делать персистный клон. и using-ом переключать на него.
>>иначе извращения неизбежны.

это я сумничал. работать с ним как с разновидностью List c особым конструированием — и нет проблем.
еще вот не нашел короткой записи для IEnumerable<x>. чем плохо стандартное сокращение x* ?
Re[3]: проблема с созданием объекта в макросе
От: VladD2 Российская Империя www.nemerle.org
Дата: 30.11.11 14:43
Оценка:
Здравствуйте, _Claus_, Вы писали:

VD>>Вообще-то никто не гарантирует, что имя типа — это корректное имя его конструктора.


_C_>Не, там где я это делаю, это динамические контейнеры. Так что усё в порядке, шеф.


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

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

_C_>Меня беспокоит только как сделать персистными варианты. В мою схему они не укладываются. но поддерживать их хотелось.


Варианты мало чем от обычных классов отличаются. Они на базе классов и реализованы. Так что не ясно в чем может быть проблема.

_C_>Если обращаться с ними как с value к примеру, а они будут иметь поля на персистные объекты — тогда фигвам получается.


А что входит в понятие "обращаться с ними как с value"?

_C_>а если они персистные, то поля должны быть трансформированы в свойства.


Странное какое-то ограничение.

_C_>выход вижу в генерации спец-персист-класса-враппера для каждого подтипа варианта и хитрое спец-вариант-свойство которое замаскирует всю механику. но это потом.


А классы у тебя поля иметь не могут, что ли? Ведь разницы быть не должно.

_C_> кортежей в полях объектов не должно быть, насколько я понимаю.


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

_C_>списки N — еще не думал, тоже просто не получится. по любому делать персистный клон. и using-ом переключать на него.

_C_>иначе извращения неизбежны.

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

Сделать это можно.

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

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

С сериализацией все относительно просто. Бежишь себе по информации об объекте и пишешь поля и/или свойства в хранилище (которое, кстати, может быть разным). Тут важно только иметь возможность указать какие поля/свойства не нужно/нужно сериализовать. Навешиваемый на объект атрибут вообще должен сериализовывать только поля.

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

Если же тип не изменяемый, или нет возможности записать все нужные данные, то нужно инициализировать объект через конструктор. Для этого нужно знать отображение полей на параметры конструктора. Для вариантов такое отображение есть. Его можно считать прямо с типа. Для кортежа, кстати, тоже. Для других типов такого отображения не будет. Тут возникает два варианта. Можно автоматически подбирать имена по соответствию названий. Если это невозможно, то нужно позволить пользователю описать отображение объекта в конструктор. Это можно сделать так:
[assembly: SerializeMap(DateTyme(Ticks))]

Отсюда можно вычислить, что сериализовать нужно свойство Ticks, а при десериализации пихать значение в конструктор с одним параметром типа long. В прочем — это почти готовый код десериализации.

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

Это избавит от всей этой байды с ручным созданием объектов и т.п.

VD>>Так что ты явно пошел неверным путем. Нужно придумать что-то другое.

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

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

VD>>Ты что пытаешься изобразить то? Какова логика?

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

А если я список захочу использовать? Списки удобная вещь. Их паттерн-матчингом можно разбирать...

_C_>еще вот задачка, хочу добавить сразу несколько методов к классу. не по одному а десяток мелких сразу в одной цитате. что-то не дает.

_C_>в принципе это возможно?

_C_>пытаюсь вот так:...

_C_>
_C_>def block = <[decl:      
_C_>        partial class $name
_C_>        {   public static convert_up(datamap: datamap_file, arr: array[exchange_struct], 
_C_>              delta:int): IEnumerable[$name]
_C_>            /*метод получения множества классов из плоского массива в базе
_C_>              delta - смещение мем-блока arr   */ 
_C_>            { empty_exchange = exchange_struct();
_C_>              size_exchange_struct = memblock.size_type(exchange_struct);
_C_>              ...
_C_>            }
_C_>            //преобразование произвольного IEnumerable[X] в массив его структур для записи в базу
_C_>            public static to_array(datamap_:datamap_file, seq: IEnumerable[$name])
_C_>            {                
_C_>                lst = List();
_C_>                ...
_C_>            }
_C_>            ...
_C_>

_C_>но компилятор много ругается..

Что говорит то?

Кстати, а зачем ты делаешь имена публичных членов не соответствующие соглашениям по именованию МС? Твой же библиотекой никто из дотнетчиков не будет пользоваться только из-за такого именования. У нас тут в парсере у вариантов поля были с маленькой буквы, так куча народа сразу заскулила. А ты вообще, какой-то олд-стайл сишный применяешь. Имена публичных членов должны быть в ПаскальКейсе.

_C_>и потом добавлю это к классу. тоже вот как добавить?


Не уверен, что прокатит. Но можно у полученного типа запросить список членов (GetMembers()) и или с помощью сплайса ..$members в другой тип вставить (это если все члены в одном списке и других нет), или в цикле вызвать Define().

Но можно и проще сделать. Помести их все в список (отдельными цитатами) и точно так сплайсом или в цикле добавь.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: проблема с созданием объекта в макросе
От: VladD2 Российская Империя www.nemerle.org
Дата: 30.11.11 15:40
Оценка:
Здравствуйте, _Claus_, Вы писали:

_C_>это я сумничал. работать с ним как с разновидностью List c особым конструированием — и нет проблем.

_C_>еще вот не нашел короткой записи для IEnumerable<x>.

В пространстве имен Nemerle.Collections есть псевдоним Seq[T]. Можешь использовать его.

_C_>чем плохо стандартное сокращение x* ?


Тем что мало кому понятно. А типов много бывает. Для каждого синтаксис вводить замучаешься. Уж если для почти строенного list[T] синтаксис не вводили, то для других подавно не нежно.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: проблема с созданием объекта в макросе
От: _Claus_  
Дата: 30.11.11 18:40
Оценка:
_C_>>Меня беспокоит только как сделать персистными варианты. В мою схему они не укладываются. но поддерживать их хотелось.
VD>Варианты мало чем от обычных классов отличаются. Они на базе классов и реализованы. Так что не ясно в чем может быть проблема.

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

_C_>>Если обращаться с ними как с value к примеру, а они будут иметь поля на персистные объекты — тогда фигвам получается.


VD>А что входит в понятие "обращаться с ними как с value"?


value- это все что может быть сохранено, но не объявлено явно как Persist.

_C_>>а если они персистные, то поля должны быть трансформированы в свойства.

VD>Странное какое-то ограничение.
Странность вызвана автоматической ленивой smart-загрузкой.
Объекты грузятся кодом свойств, для чего собственно эти все потребности и нужны.

def s = a.b //b — ссылка автоматом разрешается из базы прямо здесь, если до этого на него не ссылались.

_C_>>выход вижу в генерации спец-персист-класса-враппера для каждого подтипа варианта и хитрое спец-вариант-свойство которое замаскирует всю механику. но это потом.

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

п. 1

_C_>> кортежей в полях объектов не должно быть, насколько я понимаю.


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


так отож.


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


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

VD>Сделать это можно.

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

это полезная штука. когда сотни тысяч объектов, и они связаны в графы-деревья и нужен быстрый прозрачный доступ — альтернатив нет для .Net.

VD>С сериализацией все относительно просто. Бежишь себе по информации об объекте и пишешь поля и/или свойства в хранилище (которое, кстати, может быть разным). Тут важно только иметь возможность указать какие поля/свойства не нужно/нужно сериализовать. Навешиваемый на объект атрибут вообще должен сериализовывать только поля.


те которые нужно сохранять нужно метятся REF, VAL, .. остальные не сохраняются.


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


я подобным решением-механизмом успешно пользуюсь уже 10 лет. сначала на С++, потом на Boo.

VD>А если я список захочу использовать? Списки удобная вещь. Их паттерн-матчингом можно разбирать...


все будет. списки не вопрос.

VD>Что говорит то?


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

    private str2expr(name : string): PExpr
    /*генерация PExpr для составных имен*/
      PExpr.FromQualifiedIdentifier((Manager,name))

    public yyy(): void 
      def name = expr("xxx")
      
      def block = <[decl:      
        partial class $name //не проходит
        {   public static convert_up(datamap: datamap_file, arr: array[exchange_struct],



а такой вариант заработал


      def cname = "xxx"
      
      def block = <[decl:      
        partial class $(cname: dyn) //проходит


но это я понял, вот добавляю я это описание
typer.Env.Define(block).Compile()

а при генерации —

C:\Program Files\Nemerle\Net-4.0\Nemerle.MSBuild.targets(219,9): error : internal compiler error: assertion ``this.tenv == null'' failed in file ncc\hierarchy\TypeBuilder.n, line 884

неохота сильно дробить, там и методы и члены, конструкторы..

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


так я оттуда и есть. как заработает все, поменяю, если надо. только все эти методы и классы невидимы для прикладника (кроме datamap_file).
все остальное под капотом.

_C_>>и потом добавлю это к классу. тоже вот как добавить?


VD>Не уверен, что прокатит. Но можно у полученного типа запросить список членов (GetMembers()) и или с помощью сплайса ..$members в другой тип вставить (это если все члены в одном списке и других нет), или в цикле вызвать Define().


вроде на этапе BeforeTypedMembers, где я добавляю partial описание, раздельные описания допустимы. с чего бы я не мог записать этот код в реестр?
компилятор видит, что класс один, объединяет, а потом вышеуказанный assert.
Re[4]: проблема с созданием объекта в макросе
От: _Claus_  
Дата: 30.11.11 22:39
Оценка:
VD>Не уверен, что прокатит. Но можно у полученного типа запросить список членов (GetMembers()) и или с помощью сплайса ..$members в другой тип вставить (это если все члены в одном списке и других нет), или в цикле вызвать Define().

через GetMembers получилось нормально.

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

       <[
        class dummy
        {   static empty_exchange : exchange_struct;
            static size_exchange_struct : int = memblock.size_type(typeof(exchange_struct));
            
            public static convert_up(datamap: datamap_file, arr: array[exchange_struct], mutable delta:int): Seq[$name]
            
            //сбой при генерации этого метода
            { 
              foreach(st in arr)
              {                                
                yield if (st != empty_exchange) $name(datamap, st, delta) else null;                                                     
                delta += size_exchange_struct;
              }           
            }


error : Internal compiler error 'e = block (_N_return) :
DEBUG_INFO(block (_N_MoveNext_exit) :
DEBUG_INFO(match (DEBUG_INFO(_N_state)) {
| 0 =>
()
| _ =>
_N_MoveNext_exit (false)
};
block (_N_return) :
macro_Nemerle.Core.foreachMacro:
def cached_collection = arr;
macro_Nemerle.Core.forMacro:
def index = (0 :> int);
(block (_N_break) :
def loop() : void
{
macro_Nemerle.Core.whenmacroMacro:
when ((<.s (index, cached_collection.Length) : bool)) {
((block (_N_continue) :
match (cached_collection [index]) {
| (_) as st =>
DEBUG_INFO(_N_current = macro_Nemerle.Core.ifMacro:
DEBUG_INFO(if ((!=.ref (st, x.empty_exchange) : bool)) {
DEBUG_INFO(x (datamap, st, delta))
}
else {
DEBUG_INFO(null)
});
_N_state = 1;
_N_MoveNext_exit (true);
l4216:
();
DEBUG_INFO(macro_Nemerle.Core._N_operator_843204731_4199Macro:
[Cache:delta]]
[CacheRef:delta]] = +.s ([CacheRef:delta]], x.size_exchange_struct)));
()
| _ =>
()
} : void);
macro_Nemerle.Core._N_operator_844122235_4195Macro:
[Cache:index]]
[CacheRef:index]] = ++.i4.s ([CacheRef:index]]);
loop () : void)
}
}
loop () : void);
false))', please report a bug to bugs.nemerle.org. You can try modifying program near this location.
C:\Program Files\Nemerle\Net-4.0\Nemerle.MSBuild.targets(219,9): error : internal compiler error: assertion failed in file ncc\typing\Typer.n, line 4381: e = block (_N_return) :
DEBUG_INFO(block (_N_MoveNext_exit) :
DEBUG_INFO(match (DEBUG_INFO(_N_state)) {
| 0 =>
()
| _ =>
_N_MoveNext_exit (false)
};
block (_N_return) :
macro_Nemerle.Core.foreachMacro:
def cached_collection = arr;
macro_Nemerle.Core.forMacro:
def index = (0 :> int);
(block (_N_break) :
def loop() : void
{
macro_Nemerle.Core.whenmacroMacro:
when ((<.s (index, cached_collection.Length) : bool)) {
((block (_N_continue) :
match (cached_collection [index]) {
| (_) as st =>
DEBUG_INFO(_N_current = macro_Nemerle.Core.ifMacro:
DEBUG_INFO(if ((!=.ref (st, x.empty_exchange) : bool)) {
DEBUG_INFO(x (datamap, st, delta))
}
else {
DEBUG_INFO(null)
});
_N_state = 1;
_N_MoveNext_exit (true);
l4216:
();
DEBUG_INFO(macro_Nemerle.Core._N_operator_843204731_4199Macro:
[Cache:delta]]
[CacheRef:delta]] = +.s ([CacheRef:delta]], x.size_exchange_struct)));
()
| _ =>
()
} : void);
macro_Nemerle.Core._N_operator_844122235_4195Macro:
[Cache:index]]
[CacheRef:index]] = ++.i4.s ([CacheRef:index]]);
loop () : void)
}
}
loop () : void);
false))
в Nemerle.Compiler.Typer.AddYieldStateMachine(TExpr e) в C:\MyProjects\rsdn-nemerle-25424df\ncc\typing\Typer.n:строка 4381
в Nemerle.Compiler.Typer.RunTyper() в C:\MyProjects\rsdn-nemerle-25424df\ncc\typing\Typer.n:строка 441
в Nemerle.Compiler.Typer.TypeLocalFunction(list`1 functions) в C:\MyProjects\rsdn-nemerle-25424df\ncc\typing\Typer.n:строка 2549
в Nemerle.Compiler.Typer.DoType(PExpr expression, TypeVar expected, Boolean is_toplevel_in_seq) в C:\MyProjects\rsdn-nemerle-25424df\ncc\typing\Typer.n:строка 1633
в Nemerle.Compiler.Typer.TypeExpr(PExpr expr, TypeVar expected, Boolean is_toplevel_in_seq) в C:\MyProjects\rsdn-nemerle-25424df\ncc\typing\Typer.n:строка 1397
в Nemerle.Compiler.Typer.DoType(PExpr expression, TypeVar expected, Boolean is_toplevel_in_seq) в C:\MyProjects\rsdn-nemerle-25424df\ncc\typing\Typer.n:строка 2177
в Nemerle.Compiler.Typer.TypeExpr(PExpr expr, TypeVar expected, Boolean is_toplevel_in_seq) в C:\MyProjects\rsdn-nemerle-25424df\ncc\typing\Typer.n:строка 1397
в Nemerle.Compiler.Typer.TypeExpr(PExpr e, TypeVar expected) в C:\MyProjects\rsdn-nemerle-25424df\ncc\typing\Typer.n:строка 1366
в Nemerle.Compiler.Typer.RunTyper() в C:\MyProjects\rsdn-nemerle-25424df\ncc\typing\Typer.n:строка 408
в Nemerle.Compiler.Typer.RunFullTyping() в C:\MyProjects\rsdn-nemerle-25424df\ncc\typing\Typer.n:строка 298
в Nemerle.Compiler.MethodBuilder.RunBodyTyper() в C:\MyProjects\rsdn-nemerle-25424df\ncc\hierarchy\ClassMembers.n:строка 932
в Nemerle.Compiler.MethodBuilder.Compile() в C:\MyProjects\rsdn-nemerle-25424df\ncc\generation\HierarchyEmitter.n:строка 1115
в Nemerle.Compiler.TypeBuilder.EmitImplementation() в C:\MyProjects\rsdn-nemerle-25424df\ncc\generation\HierarchyEmitter.n:строка 653
в Nemerle.Compiler.TypesManager._N_emit_impl__58456.apply_void(TypeBuilder ti) в C:\MyProjects\rsdn-nemerle-25424df\ncc\generation\HierarchyEmitter.n:строка 370
в Nemerle.Compiler.TypesManager._N_maybe_f__58691.apply_void(TypeBuilder ti) в C:\MyProjects\rsdn-nemerle-25424df\ncc\hierarchy\TypesManager.n:строка 257
в Nemerle.Collections.NList.Iter[T](list`1 l, FunctionVoid`1 f) в C:\MyProjects\rsdn-nemerle-25424df\lib\list.n:строка 926
в Nemerle.Core.list`1.Iter(FunctionVoid`1 f) в C:\MyProjects\rsdn-nemerle-25424df\lib\list.n:строка 317
в Nemerle.Compiler.TypesManager.Iter(list`1 builders, FunctionVoid`1 f) в C:\MyProjects\rsdn-nemerle-25424df\ncc\hierarchy\TypesManager.n:строка 264
в Nemerle.Compiler.TypesManager.Iter(FunctionVoid`1 f) в C:\MyProjects\rsdn-nemerle-25424df\ncc\hierarchy\TypesManager.n:строка 275
в Nemerle.Compiler.TypesManager.compile_all_tyinfos(Boolean aux_phase) в C:\MyProjects\rsdn-nemerle-25424df\ncc\generation\HierarchyEmitter.n:строка 397
в Nemerle.Compiler.TypesManager._N__N_lambda__57878__57982.apply_void() в C:\MyProjects\rsdn-nemerle-25424df\ncc\generation\HierarchyEmitter.n:строка 240
в Nemerle.Compiler.Solver.Enqueue(FunctionVoid action) в C:\MyProjects\rsdn-nemerle-25424df\ncc\typing\Solver.n:строка 199
в Nemerle.Compiler.TypesManager.EmitDecls() в C:\MyProjects\rsdn-nemerle-25424df\ncc\generation\HierarchyEmitter.n:строка 239
в Nemerle.Compiler.ManagerClass.Run() в C:\MyProjects\rsdn-nemerle-25424df\ncc\passes.n:строка 608
в Nemerle.CommandlineCompiler.MainClass.main_with_catching() в C:\MyProjects\rsdn-nemerle-25424df\ncc\main.n:строка 130
Re[5]: проблема с созданием объекта в макросе
От: VladD2 Российская Империя www.nemerle.org
Дата: 01.12.11 00:23
Оценка:
Здравствуйте, _Claus_, Вы писали:

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


А, если не null, а какое-то другое значение?

ЗЫ

Подозреваю, что проблема преобразовании в итератор. Хорошо бы создать обособленный минимальный пример воспроизводящий ошибку. Тогда бы я смог поглядеть что там происходит.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: проблема с созданием объекта в макросе
От: _Claus_  
Дата: 01.12.11 07:46
Оценка:
VD>Подозреваю, что проблема преобразовании в итератор. Хорошо бы создать обособленный минимальный пример воспроизводящий ошибку. Тогда бы я смог поглядеть что там происходит.


namespace DBLib
  
  [MacroUsage(MacroPhase.BeforeTypedMembers, MacroTargets.Class)]\
  macro Persist(typeBuilder : TypeBuilder)
  
    ClassFormer(typeBuilder)

  [ManagerAccess(ManagerClass.Instance)]\
  class ClassFormer
    typeBuilder :TypeBuilder
    
    private str2expr(name : string): PExpr
    /*генерация PExpr для составных имен*/
      PExpr.FromQualifiedIdentifier((Manager,name))
    
    public this(tb : TypeBuilder)      
      typeBuilder = tb
      
      def name = str2expr("x")
            
      def block = <[decl:      
        class dummy
        {   static empty_exchange : exchange_struct;
            static size_exchange_struct : int = memblock.size_type(typeof(exchange_struct));
            
            public static convert_up(datamap: datamap_file, arr: array[exchange_struct], mutable delta:int): Seq[$name]
            /*метод получения множества классов из плоского массива в базе
              delta - смещение мем-блока arr   */ 
            { 
              foreach(st in arr)
              { 
                when (st != empty_exchange) yield null                
                
              }           
            }
          }
         ]>


вызов:

using DBLib

[Persist]\
partial class x 
  public struct exchange_struct
    i : int
Re[7]: проблема с созданием объекта в макросе
От: _Claus_  
Дата: 01.12.11 07:59
Оценка:
в конце конструктора ClassFormer еще вот такое добавить надо


foreach(member in block.td.GetMembers())
        tb.DefineWithSource(member)
Re[7]: проблема с созданием объекта в макросе
От: VladD2 Российская Империя www.nemerle.org
Дата: 01.12.11 14:19
Оценка:
Здравствуйте, _Claus_, Вы писали:

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


_C_>
_C_>namespace DBLib...
_C_>                when (st != empty_exchange) yield null
_C_>


ОК, постараюсь в ближайшее время глянуть, что там не так. Пока придется без использования yield пережить. Воспользуйся промежуточной коллекций. Или вынеси код в библиотечный метод.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[8]: проблема с созданием объекта в макросе
От: _Claus_  
Дата: 01.12.11 15:17
Оценка:
VD>ОК, постараюсь в ближайшее время глянуть, что там не так. Пока придется без использования yield пережить. Воспользуйся промежуточной коллекций. Или вынеси код в библиотечный метод.
уже. но вылезла другая беда:


имею ошибку error : expected x, got object in function body: System.Object is not a subtype of x [simple require]
и не могу понять что ее вызывает.
все добавляю через DefineWithSource, а оно никак не показывает в сгенеренном файле причину — показывает на место вызова.
что это может вызвать? грешил на вызовы конструкторов, отключал их параметры, потом насовсем, так вроде не они.

на всяк случай код вызова:


[ManagerAccess(ManagerClass.Instance)]\
  class ClassFormer
    typeBuilder :TypeBuilder
    
    private str2expr(name : string): PExpr
    /*генерация PExpr для составных имен*/
      PExpr.FromQualifiedIdentifier((Manager,name))
    
    public this(tb : TypeBuilder)      
      typeBuilder = tb
      
      def name = str2expr("x")
      
      def save_block = tb.UserData["str_saves"] :> list[PExpr] ?? []
      
      //typeBuilder.GetMemType()
      
      def block = <[decl:      
        class dummy /*для копирования из него членов и методов*/
        {               
            static size_exchange_struct : int = memblock.size_type(typeof(exchange_struct));
            
            public static convert_up(datamap: datamap_file, arr: array[exchange_struct], mutable delta:int): array[$name]
            /*метод получения множества классов из плоского массива в базе, delta - смещение мем-блока в arr */ 
            { 
              mutable count = 0;              
              def result = array(arr.Length);
              
              foreach( st in arr)
              { 
                result[count] = if (st._null) null else $(tb.ParsedTypeName)();//(datamap, st, delta);                   
                delta += size_exchange_struct;                
                ++count;
              }
              result
            }
            //преобразование произвольного IEnumerable[X] в массив его структур для записи в базу
            public static to_array(datamap:datamap_file, seq: Seq[$name]) : array[exchange_struct]
            {                
                def lst = List();
                                    
                foreach (o in seq)
                  if (o != null)
                  {   
                    o.datamap = datamap;                                    
                    o.save_strings()    ;                                
                    lst.Add(o._exchange) ;
                  }
                  else
                  { def st = exchange_struct();
                    st._null = true;
                    lst.Add(st);
                  }              
                lst.ToArray();
             }
                            
            //загрузка одного объекта, на который может быть много ссылок    
            public static load(datamap:datamap_file, delta:int): $name
            {                
                mutable obj;                           
                unless (delta == 0 || datamap.map_objects.TryGetValue(delta, out obj))                     
                {
                  obj = $(tb.ParsedTypeName)();//(datamap, delta)     ;                       
                  datamap.map_objects[delta] = obj;
                }            
                obj
              }           
            //метод для считывая объекта из базы. может понабиться при отмене изменений
            //public force_load(replace:bool): $name 
            //{ 
            //    def new_val = $(tb.ParsedTypeName)(datamap, datamap.load.[exchange_struct](address), address);
                
            //    when (replace)
            //      datamap.map_objects[address] = new_val;                
            //    new_val
            //}                
            public save_null(): void
            //метит в массиве как null
            { _exchange._null = true;
              when (address != 0)
                save();     
            }
            //сохраняет все строки объекта
            public save_strings(): void
            {                
               ..$save_block
            }            
            //сохраняет объект                        
            public save(): void
            {                
                save_strings();                            
                datamap.write(_exchange, ref address);
            }                        
            //файл базы, откуда объект
            //одновременно можно работать с несколькими базами                        
            public mutable datamap: datamap_file;                        
            //смещение в базе                        
            public mutable address: int;
            
            //объявление типа структуры                                                            
            public this() {}
                                            
            public this(dmap:datamap_file)
            {                
                datamap = dmap
            }                
            public this(dmap:datamap_file, addr:int)
            {                
                datamap = dmap;                            
                address = addr;                            
                _exchange = datamap.load.[exchange_struct](address);
            }                            
            public this(dmap:datamap_file, data_class:exchange_struct, addr:int)
            {                
                datamap = dmap;                            
                _exchange = data_class;                            
                address = addr;
            }           
          } ]> 
    
      foreach(member in block.td.GetMembers())
        tb.DefineWithSource(member)
Re[8]: проблема с созданием объекта в макросе
От: _Claus_  
Дата: 01.12.11 15:44
Оценка:
докумекал я — проблема была в неявном преобразовании, которое Н отказывался делать. в Boo это автоматом, а здесь все укажи да расскажи.

           public static load(datamap:datamap_file, delta:int): $name
            {                
                mutable obj;                           
                unless (delta == 0 || datamap.map_objects.TryGetValue(delta, out obj))                     
                {
                  obj = $(tb.ParsedTypeName)();//(datamap, delta)     ;                       
                  datamap.map_objects[delta] = obj;
                }            
                obj :> $name //вместо obj
              }
Re[9]: проблема с созданием объекта в макросе
От: VladD2 Российская Империя www.nemerle.org
Дата: 01.12.11 15:51
Оценка:
Здравствуйте, _Claus_, Вы писали:

_C_>имею ошибку error : expected x, got object in function body: System.Object is not a subtype of x [simple require]


Сообщение случаем не руками переписывал? Может там было нечто вроде "expected x, got object+ in function body"?

Сообщение это означает, что тип выражения в теле метода вывелся как "object", а метод описан как возвращающий "x" (что за "х", кстати?). Если там у object еще "+", есть, это это может означать, что ты где-то в теле использовал null, а тип
x с ним не совместим (например, вэлью-тип или параметр типа не имеющего ограничение class).

Вот пример демонструющий это дело:
  Test() : int // сообщение будет выдано на "int"
  {
    null
  }

Этот код выдаст сообщение:

error : expected int, got object+ in function body: the `null' literal is not a valid value of type int


_C_>[ManagerAccess(ManagerClass.Instance)]\


Так делать не надо. ManagerClass.Instance — это рудимент. Со временем его уберут. Так что если нужен ManagerClass, то передавай его явно через параметры конструктора или получай из других объектов (они много где есть).


_C_>      def name = str2expr("x")

Ну, вот он этот загадочный тип "x". Зачем ты его явного то задаешь? Это похоже на баг.

А — это:

_C_>            //загрузка одного объекта, на который может быть много ссылок    
_C_>            public static load(datamap:datamap_file, delta:int): $name
_C_>            {                
_C_>                mutable obj;
_C_>                unless (delta == 0 || datamap.map_objects.TryGetValue(delta, out obj))                     
_C_>                {
_C_>                  obj = $(tb.ParsedTypeName)();//(datamap, delta)     ;                       
_C_>                  datamap.map_objects[delta] = obj;
_C_>                }            
_C_>                obj
_C_>              }

скорее всего ошибка (отбито так плохо, что найти конец метода трудно).

Скорее всего map_objects это хэш-таблица хранящая в качестве значения элементы типа object. Естественно, что возвращая obj (типа object) вместо "х" ничего хорошего не получишь.

Здесь, скорее всего, нужно вставлять принудительное приведение типов:
obj :> $name


Ну, а сообщение в никуда указывает (скорее всего) из-за того, что локешон для него берется из описания типа. А он инспирирование твоим макросом. Вот его локешон и используется.

Возможно, с нашей стороны, не самым разумным решением было "вешать" сообщение на описание типа функции. Сообщение, реально, относится к телу функции. Раньше оно на нем и висело, но все равно нельзя было понять к чему оно относится. Можно попробовать перевесить на закрывающую скобку, но опять же могут быть эффекты.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[10]: проблема с созданием объекта в макросе
От: _Claus_  
Дата: 01.12.11 16:07
Оценка:
VD>Сообщение случаем не руками переписывал? Может там было нечто вроде "expected x, got object+ in function body"?
точно такое. копировал


VD>Ну, вот он этот загадочный тип "x". Зачем ты его явного то задаешь? Это похоже на баг.

это тест код. пробовал, подбирал варианты.

VD>скорее всего ошибка (отбито так плохо, что найти конец метода трудно).

таки точно здесь.

VD>Скорее всего map_objects это хэш-таблица хранящая в качестве значения элементы типа object. Естественно, что возвращая obj (типа object) вместо "х" ничего хорошего не получишь.

привет к автомату. но это мелочь.

VD>Возможно, с нашей стороны, не самым разумным решением было "вешать" сообщение на описание типа функции. Сообщение, реально, относится к телу функции. Раньше оно на нем и висело, но все равно нельзя было понять к чему оно относится. Можно попробовать перевесить на закрывающую скобку, но опять же могут быть эффекты.


оно вообще показывает не в макрокод, а в использующую стороку — [Persist]class x.
поэтому, если б оно показало а) в сгенерированный макрос и б) на последний statement — сразу было бы понятно. мне. спасибо!
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.