Здравствуйте, Don Reba, Вы писали:
DR>В Немерле не появилась возможность выполнять действия в конце компиляции?
DR>Нужно сгенерировать класс имеющий информацию о всей программе.
В конце компиляции это сделать уже будет невозможно.
Что за информация нужна в этом классе?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Здравствуйте, Don Reba, Вы писали:
DR>Как же так? Даже в вызове файналайзера модуля можно создать новый класс. Конечно, это нехорошо. Хотелось бы иметь более надёжный метод.
Ниже приведен метод со стадиями компиляции. Я там добавил коментарий после которого добавление новых типо невозможно или черевато проблемами.
http://nemerle.org/svn/nemerle/trunk/ncc/hierarchy/TypesManager.n
/**
* Main function of type declaration handling pass.
*
* <remarks>
* - constructing typing environments [TypeBuilder.make_tyenvs]
* - binding types [TypeBuilder.bind_types]
* - determining subtyping relations [TypeBuilder.determine_subtyping]
* - checking subtyping constraints on types that are already bound
* [TypeBuilder.check_bound_types]
* - adding members [TypeBuilder.add_members]
* - adding the variant/variant option special matching methods
* </remarks>
*/
public Run () : void
{
ExpandMacros ();
foreach (x : TypeBuilder in infos.Reverse ())
Util.locate (x.Location, x.process_macro_attributes (MacroPhase.BeforeInheritance));
run_phase = 1;
SourceTopIter (fun (x : TypeBuilder) { x.make_tyenvs () });
run_phase = 2;
SourceTopIter (fun (x : TypeBuilder) { x.bind_types () });
// add the _N_GetVariantCode methods to variants and variant options
Iter (fun (x : TypeBuilder) { x.add_special_variant_methods () });
run_phase = 3;
determine_subtyping ();
run_phase = 4;
Iter (fun (x : TypeBuilder) { x.check_bound_types () });
run_phase = 5;
ExpandMacros ();
Iter (fun (x : TypeBuilder) { x.process_macro_attributes (MacroPhase.BeforeTypedMembers) });
//// Поле этой стадии добавлять типы опасно
run_phase = 6;
Iter (fun (x : TypeBuilder) { x.add_members () });
run_phase = 7;
ExpandMacros ();
Iter (fun (x : TypeBuilder) { x.process_macro_attributes (MacroPhase.WithTypedMembers) });
// add constant object constructors for constant variant options
Iter (fun (x : TypeBuilder) { x.add_constant_variant_ctors () });
// propagate the SpecialName attribute if needed
Iter (fun (x : TypeBuilder) {
when (x.Attributes %&& NemerleAttributes.SpecialName)
x.mark_members_with_special_name ()
});
def check_method_implements (ti : TypeBuilder) {
unless (ti.IsInterface) ti.resolve_method_implements ();
};
Iter (check_method_implements);
Iter (fun (x : TypeBuilder) { x.check_ctor_constraints () });
when (generatedSourceCode != null)
try {
using (genSrcFile = System.IO.StreamWriter (nameOfGeneratedSourceFile ()))
genSrcFile.Write (generatedSourceCode.ToString ());
}
catch {
| e => Message.Warning ("could not save generated source code file: " + e.Message)
}
}
И это стадия типизации. А еще есть стадии генерации сборок и т.п. На них вообще нельзя типы создавать новые.
VD>>Что за информация нужна в этом классе?
DR>Статистика для выделения памяти. В принципе, ничего что нельзя было бы вычислять постепенно. Просто, так больше возни.
Более подробно можно?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, Don Reba, Вы писали:
VD>Ниже приведен метод со стадиями компиляции. Я там добавил коментарий после которого добавление новых типо невозможно или черевато проблемами.
VD>http://nemerle.org/svn/nemerle/trunk/ncc/hierarchy/TypesManager.n
Это прояснило некоторые вещи, спасибо.
VD>Более подробно можно?
Сейчас пытаюсь развить твой макрос локализации строк. Класс загружающий локализированные строки должен справляться с неполными переводами, например, от предыдущих версий программы.
Генерируемому классу необходим список всех локализируемых строк. У меня не получается его реализовать. Момент когда доступны все строки неизвестен, а модифицировать класс по мере нахождения новых строк не получается. Если создать метод через DefineAndReturn, компилятор жалуется на отсутствие method_base.
Здравствуйте, Don Reba, Вы писали:
DR>Сейчас пытаюсь развить твой макрос локализации строк. Класс загружающий локализированные строки должен справляться с неполными переводами, например, от предыдущих версий программы.
Понятно.
DR>Генерируемому классу необходим список всех локализируемых строк.
А можно класс генерировать сначало, а уже потом добавлять в него все что нужно в виде кода методов? Код методов можно изменять значительно дольше чем описания самих классов.
DR> У меня не получается его реализовать. Момент когда доступны все строки неизвестен, а модифицировать класс по мере нахождения новых строк не получается. Если создать метод через DefineAndReturn, компилятор жалуется на отсутствие method_base.
Со строками все довольно сложно. Дело в том, что строка может появиться в процессе работы макросса, а значит и в процессе типизации методов.
Добавить события не проблема. Вопрос в том какие события нужны ?
В принципе можно добавить событие на самое начало компиляции (что-то вроде "BeforeCompileProject", в принципе уже есть событие OnInit у ManagerClass (дуступен как свойсво Manager почти везде, но неясно как его установить заранее)), по одному для каждой стадии компиляции (т.е. BeforeInheritance, BeforeTypedMembers и WithTypedMembers) и один на окончание типизации.
Вопрос только как запустить код который установит события.
В моем макросе код запускался в следствии выполнения макроса уровня сборки работющего на ранних стадиях типизации. Но макрос может быть вызван несколько раз (например, есть вда объявления в разных файлах), а события нужно подключать один раз. Причем в Интеграции это вообще нужно делать один раз.
В общем, нужно все как слеудет продумать.
... << RSDN@Home 1.2.0 alpha rev. 637>>