Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Codegen needs to respect ordering of declarations for templated types #66

Open
termi-official opened this issue Nov 15, 2024 · 0 comments

Comments

@termi-official
Copy link
Contributor

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant