wrapit icon indicating copy to clipboard operation
wrapit copied to clipboard

Codegen needs to respect ordering of declarations for templated types

Open termi-official opened this issue 1 year ago • 0 comments

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).

termi-official avatar Nov 15 '24 13:11 termi-official