Skip to content

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

Description

@termi-official

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions