Codegen needs to respect ordering of declarations for templated types
Right now the generated entry point define_julia_module starts with adding the wrappers, i.e.
std::vector<std::shared_ptr<Wrapper>> wrappers = {
....
};
followed by adding enums. This leads to faulty codegen for templates which are parametrized in terms of enums.
MWE
template <class T>
class C {
};
enum E {
E1,
E2
};
void f(C<E> a) {}
void f(C<C<E>> a) {}
Which leads to a runtime error C++ exception while wrapping module Hello: No appropriate factory for type 1E.
I think the problem above can be easily fixed. I usually opt for moving the relevant wrapper code around after the code has been generated manually. However, this example also has a more tricky issue. If we have recursive tempalte definitions we also need to sort the t.apply code. For the code as above the codegen would be
// Class generating the wrapper for type C
// signature to use in the veto file: C
struct JlC: public Wrapper {
JlC(jlcxx::Module& jlModule): Wrapper(jlModule){
DEBUG_MSG("Adding wrapper for type C (" __HERE__ ")");
// defined in ./A.h:77:7
jlcxx::TypeWrapper<jlcxx::Parametric<jlcxx::TypeVar<1>>> t = jlModule.add_type<jlcxx::Parametric<jlcxx::TypeVar<1>>>("C");
type_ = std::unique_ptr<jlcxx::TypeWrapper<jlcxx::Parametric<jlcxx::TypeVar<1>>>>(new jlcxx::TypeWrapper<jlcxx::Parametric<jlcxx::TypeVar<1>>>(jlModule, t));
t.constructor<>(/*finalize=*/jlcxx::finalize_policy::yes);
auto t1_decl_methods = [this]<typename T> (jlcxx::TypeWrapper<C<T>> wrapped){
auto module_ = this->module_;
wrapped.template constructor<>(/*finalize=*/jlcxx::finalize_policy::yes);
};
t.apply<C<C<E>>, C<E>>(t1_decl_methods); // <----------------- relevant line -----------
}
void add_methods() const{
}
private:
std::unique_ptr<jlcxx::TypeWrapper<jlcxx::Parametric<jlcxx::TypeVar<1>>>> type_;
};
std::shared_ptr<Wrapper> newJlC(jlcxx::Module& module){
return std::shared_ptr<Wrapper>(new JlC(module));
}
where t.apply<C<C<E>>, C<E>>(t1_decl_methods); should be t.apply<C<E>, C<C<E>>>(t1_decl_methods);.
Another related issue here is that t.apply is sometimes incomplete, but I can not come up with a reproducer in a simple example. Essentially I can observe, that sometimes apply does not contain the templates for basic types (e.g. int, float, double).