Наткнулся не непонятности с вариантами, все дело в том что понадобилось создать вариант в макросе уровня класса, добавить вариант можно так обычным способом
<[ variant Test {} ]>
, но нужно добавлять динамически VariantOption пытался сделать квазицитатой:
<[decl: | $(name : usesite) {} ]>
, но он распознает это как EnumOption, вопрос первый как создать цитату VariantOption ?
Далее пытался создать обходными путями например так:
создать пустышку
но после когда запускаем ty.DefineNested(decl).Compile();
Выдается NRE связанное с ошибкой внутренних структур TypeBuilder, которое не знаю как исправить, боюсь что и в любых других способах добавления variant option будет NRE, есть ли у сообщества мысли по поводу решения этой проблемы?
Здравствуйте, hardcase, Вы писали:
H>Здравствуйте, CodingUnit, Вы писали:
CU>>, но нужно добавлять динамически VariantOption пытался сделать квазицитатой: CU>>
CU>><[decl: | $(name : usesite) {} ]>
CU>>
CU>>, но он распознает это как EnumOption, вопрос первый как создать цитату VariantOption ?
H>Возможно что вот так заработает: H>
Здравствуйте, catbert, Вы писали:
C>использовать <[case: .... ]> (не уверен, что именно case), или просто вручную создать кусок AST это не баг, просто парсеру не хватает контекста
вручную создать кусок Ast я пробовал, но после как я сказала при компиляции в TypeBuilder получается NRE
Здравствуйте, CodingUnit, Вы писали:
CU>Наткнулся не непонятности с вариантами, все дело в том что понадобилось создать вариант в макросе уровня класса, добавить вариант можно так обычным способом CU>
CU><[ variant Test {} ]>
CU>
CU>, но нужно добавлять динамически VariantOption пытался сделать квазицитатой: CU>
CU><[decl: | $(name : usesite) {} ]>
CU>
CU>, но он распознает это как EnumOption, вопрос первый как создать цитату VariantOption ?
Вот пример из стандартной библиотеки макросов:
<[ case: | x is $(param.Type) => this.$(m.header.PName : name) (x) ]>
И вообще, если возникают вопросы по макрам, то лучший выход (ну, кроме вопросов здесь) — это чтение исходников компилятора и стандартной библиотеки.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, CodingUnit, Вы писали:
CU>Здравствуйте, catbert, Вы писали:
C>>использовать <[case: .... ]> (не уверен, что именно case), или просто вручную создать кусок AST это не баг, просто парсеру не хватает контекста
CU>вручную создать кусок Ast я пробовал, но после как я сказала при компиляции в TypeBuilder получается NRE
Какой этап компиляции? Compile вызывать нужно не на Option-е, а на самой варианте.
Здравствуйте, VladD2, Вы писали:
CU>>, но он распознает это как EnumOption, вопрос первый как создать цитату VariantOption ?
VD>Вот пример из стандартной библиотеки макросов: VD>
VD><[ case: | x is $(param.Type) => this.$(m.header.PName : name) (x) ]>
VD>
VD>И вообще, если возникают вопросы по макрам, то лучший выход (ну, кроме вопросов здесь) — это чтение исходников компилятора и стандартной библиотеки.
Влад, разговор идет не о ветке матча, а о ветке варианта.
Здравствуйте, CodingUnit, Вы писали:
CU>Наткнулся не непонятности с вариантами, все дело в том что понадобилось создать вариант в макросе уровня класса, добавить вариант можно так обычным способом CU>
CU><[ variant Test {} ]>
CU>
CU>, но нужно добавлять динамически VariantOption пытался сделать квазицитатой: CU>
CU><[decl: | $(name : usesite) {} ]>
CU>
CU>, но он распознает это как EnumOption, вопрос первый как создать цитату VariantOption?
Похоже, что это упущение. Постараюсь исправить его в ближайшее время.
CU>Далее пытался создать обходными путями например так: CU>создать пустышку CU>
CU>def td= <[
CU> variant Dummy
CU> {
CU> | $(name : usesite) {}
CU> } ]>;
CU>def opt = td.td.GetMembers().Head;
Это какой-то уж очень обходной путь :).
CU>def opts = // .. собираем множество options
CU>def decl=<[ variant Test
CU>{
CU> ..$opts
CU>} ]>;
CU>
CU>но после когда запускаем ty.DefineNested(decl).Compile(); CU>Выдается NRE
Типы нужно добавлять с помощью метода DefineNestedType. NRE, скорее всего, связан с этим.
Но сама идея, создавать вхождения вариантов в левых вариантах, не самая хорошая. Могут появиться другие проблемы.
Ниже я привел пример как создать вхождение варианта вручную (без квази-цитирования). Пока в компиляторе не поддерживается цитата для этого, лучше поступать так.
Код макро-атрибута создающего вхождение по заданному имени:
using Nemerle;
using Nemerle.Collections;
using Nemerle.Compiler;
using Nemerle.Compiler.Parsetree;
using Nemerle.Text;
using Nemerle.Utility;
using System;
using System.Collections.Generic;
using System.Linq;
namespace MacroLibrary1
{
[MacroUsage(MacroPhase.BeforeInheritance, MacroTargets.Class)]
macro DefineVariantOption(tb : TypeBuilder, optionName)
{
DefineVariantOptionImpl.DoTransform(tb, Macros.ImplicitCTX(), optionName)
}
module DefineVariantOptionImpl
{
public DoTransform(tb : TypeBuilder, typer : Typer, optionName : PExpr) : void
{
Macros.DefineCTX(typer);
def optionNameStr = optionName.ToString();
def name = Splicable.Name(Macros.UseSiteSymbol(optionNameStr));
def modifiers = Modifiers(0, []);
def variantOption =
ClassMember.TypeDeclaration(name, modifiers,
TopDeclaration.VariantOption(name, modifiers, Typarms.Empty, []));
def variantOptionBuilder = tb.DefineNestedType(variantOption);
variantOptionBuilder.Compile();
}
}
}
Использование макроса:
using System.Console;
using MacroLibrary1;
[DefineVariantOption(GeneratedOption1)]
variant Test
{
}
module Program
{
Main() : void
{
WriteLine(Test.GeneratedOption1().GetType().Name);
_ = ReadLine();
}
}
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, hardcase, Вы писали:
H>Какой этап компиляции? Compile вызывать нужно не на Option-е, а на самой варианте.
Не, Compile нужно вызвать на вхождении, но добавлять его нужно DefineNestedType. Надо бы пофиксить этот баг и вместо NRE выдавать полноценное исключение.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, CodingUnit, Вы писали:
CU>Наткнулся не непонятности с вариантами, все дело в том что понадобилось создать вариант в макросе уровня класса, добавить вариант можно так обычным способом CU>
CU><[ variant Test {} ]>
CU>
CU>, но нужно добавлять динамически VariantOption пытался сделать квазицитатой: CU>
CU><[decl: | $(name : usesite) {} ]>
CU>
CU>, но он распознает это как EnumOption, вопрос первый как создать цитату VariantOption ?
Исправил эту недоработку. Теперь создавать вхождения вариантов можно будет так:
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, CodingUnit, Вы писали:
CU>>Наткнулся не непонятности с вариантами, все дело в том что понадобилось создать вариант в макросе уровня класса, добавить вариант можно так обычным способом CU>>
CU>><[ variant Test {} ]>
CU>>
CU>>, но нужно добавлять динамически VariantOption пытался сделать квазицитатой: CU>>
CU>><[decl: | $(name : usesite) {} ]>
CU>>
CU>>, но он распознает это как EnumOption, вопрос первый как создать цитату VariantOption ?
VD>Исправил эту недоработку. Теперь создавать вхождения вариантов можно будет так: VD>
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, CodingUnit, Вы писали:
CU>>Наткнулся не непонятности с вариантами, все дело в том что понадобилось создать вариант в макросе уровня класса, добавить вариант можно так обычным способом CU>>
CU>><[ variant Test {} ]>
CU>>
CU>>, но нужно добавлять динамически VariantOption пытался сделать квазицитатой: CU>>
CU>><[decl: | $(name : usesite) {} ]>
CU>>
CU>>, но он распознает это как EnumOption, вопрос первый как создать цитату VariantOption ?
VD>Исправил эту недоработку. Теперь создавать вхождения вариантов можно будет так: VD>
Это хорошо работает на фазе BeforeInheritance, но не работает на BeforeTypedMembers, тот самый null при вызове Compile(), странно, можно ли это исправить, обычно на этой фазе можно добавлять подклассы?
Здравствуйте, CodingUnit, Вы писали:
CU>Здравствуйте, VladD2, Вы писали:
VD>>Здравствуйте, CodingUnit, Вы писали:
CU>>>Наткнулся не непонятности с вариантами, все дело в том что понадобилось создать вариант в макросе уровня класса, добавить вариант можно так обычным способом CU>>>
CU>>><[ variant Test {} ]>
CU>>>
CU>>>, но нужно добавлять динамически VariantOption пытался сделать квазицитатой: CU>>>
CU>>><[decl: | $(name : usesite) {} ]>
CU>>>
CU>>>, но он распознает это как EnumOption, вопрос первый как создать цитату VariantOption ?
VD>>Исправил эту недоработку. Теперь создавать вхождения вариантов можно будет так: VD>>
CU>Это хорошо работает на фазе BeforeInheritance, но не работает на BeforeTypedMembers, тот самый null при вызове Compile(), странно, можно ли это исправить, обычно на этой фазе можно добавлять подклассы?
Так никто и не отвечает, вызываю DefineNestedType, но возникнает null, такое видится только на фазах BeforeTypedMembers и выше, должно ли так быть? добавление обычных классов на этой фазе обычно проходит?
Здравствуйте, CodingUnit, Вы писали:
CU>Здравствуйте, CodingUnit, Вы писали:
CU>>Здравствуйте, VladD2, Вы писали:
VD>>>Здравствуйте, CodingUnit, Вы писали:
CU>>>>Наткнулся не непонятности с вариантами, все дело в том что понадобилось создать вариант в макросе уровня класса, добавить вариант можно так обычным способом CU>>>>
CU>>>><[ variant Test {} ]>
CU>>>>
CU>>>>, но нужно добавлять динамически VariantOption пытался сделать квазицитатой: CU>>>>
CU>>>><[decl: | $(name : usesite) {} ]>
CU>>>>
CU>>>>, но он распознает это как EnumOption, вопрос первый как создать цитату VariantOption ?
VD>>>Исправил эту недоработку. Теперь создавать вхождения вариантов можно будет так: VD>>>
>Это хорошо работает на фазе BeforeInheritance, но не работает на BeforeTypedMembers, тот самый null при вызове Compile(), странно, можно ли это исправить, обычно на этой фазе можно добавлять подклассы?
>Так никто и не отвечает, вызываю DefineNestedType, но возникнает null, такое видится только на фазах BeforeTypedMembers и выше, должно ли так быть? добавление обычных классов на этой фазе обычно проходит?
Здравствуйте, CodingUnit, Вы писали:
CU>>Это хорошо работает на фазе BeforeInheritance, но не работает на BeforeTypedMembers, тот самый null при вызове Compile(), странно, можно ли это исправить, обычно на этой фазе можно добавлять подклассы?
CU>Так никто и не отвечает, вызываю DefineNestedType, но возникнает null, такое видится только на фазах BeforeTypedMembers и выше, должно ли так быть? добавление обычных классов на этой фазе обычно проходит?
Это баг. Поправил.
На будущее...
1. Не стоит так оверквотить. Цитировать надо только то, что нужно для понимания написанного тобой.
2. Если чувствуешь, что нашел баг, стоит завести issue и в форуме уже дать ссылку на него. Это ускорит процесс исправления багов.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.