Skip to content

Automatically generate boilerplate code that makes wrappers easier to use #10

@haxscramper

Description

@haxscramper

Feel free to comment on this issue with extra ideas
It is intended to be used as a place to collect all
potentially useful suggestions, even though some of
them might be harder to implement.

Configuration for more sophisticated wrapper logic. A lot of additional information that is not accessible even to the C compiler (like magical int returns values) that should be handled. Previous clang-based implementation allowed passing a series of callbacks for automatically altering generation and handling of the code, but this must be generalized for tree-sitter as well.

  • Make sure non default-initializable types are handled correctly for C++ interop. Add .requiresinit. annotation if there is no default constructor provided (or default constructor is implicitly deleted etc. This information should be stored in CxxObject in form of flags, like 'copyable', 'default-constructible' etc.)
  • Convert ‘out’ arguments for C functions to nim tuple[] returns :: Need to know which parameters are in, which are out. Sometimes this is mentioned in documentation, but in general this is a "dark knowledge", not formally noted down anywhere.
  • Wrap ‘raw’ C procedures that return exit codes to raising ones :: Specify list of allowed values, and relations between regular int return and some enum definition.
  • Convert ‘macro enum groups’ into full nim enums (#define PAPI_OK 0, #define PAPI_EINVAL -1) :: It is possible to infer macro enum boundaries to some degree (if they follow certain naming pattern), but grouping based on "enum begin" and "enum end" seems less error-prone.
  • Detect C flags enums with 1 << N enum values. Provide set[E] helper interfaces for these.
  • If anonymous struct is used as a field, its fields can also be accessed directly via . - (e.g. struct A { struct {int x, y;}; }; can be used as objectOfA.x). This might interfere with generate completeStruct annotations when possible #7, so it needs to be configurable if possible.
  • Wrap C enums as two versions - one is "raw" (current version) and other is "pure" - 1:1 mapping with the original one, but without any holes in values.
    • "raw" enum might also support + operator and other low-level C mechanics
    • "pure" enum must be mappable (implicitly, this must be implemented in opt-out way for those who don't want to have implicit type conversions in their code) to the base enum type
    • something else
  • Track memory management function for C code - create nim destructors automatically when possible. Code similar to gittyup can be generated automatically.
    • Each library wrapper can automatically define "Heaps" typeclass and free functions that could be used for it. Does not really make sense to wrap everything in when, unless it is a single-file library.
    • ptr T can be wrapped in newly declared nim objects. This way, we can get proper memory management semantics using =destroy hooks. For example, git_pathspec can be wrapped as git_pathspec_c and then put into git_pathspec object as a ptr git_pathspec_c field. All low-level C library API procs are wrapped as git_pathspec_create_raw (added _raw suffix) and then additionally wrapped in the
      proc git_pathspec_create(args: ...): git_pathspec = 
        git_pathspec(data: git_pathspec_create_raw(args)
  • Wrap "method" functions that accept pointers as ones with assert arg != nil checks. For example
    func name*(remote: GitRemote): string =
      ## retrieve the name of the input
      assert remote != nil
      result = $git_remote_name(remote)
  • Merge multifile headers into one (for tree-sitter processing) using boost wave - I can conditionally enable or disable processing of the #include directive, so it is only a matter of a single predicate that controls how imports are handled.

In addition to regular source code enhancement features, it is also possible to automatically generate .nimble project files that would automatically handle installation/build and other project-related parts of the process. Similar to the https://github.com/nimterop/nimterop#build-api, but again, without the need to depend on the hcparse run/compile-time framework. An alternative solution would be to put all of this logic into a small no-dependency package and make all generated wrappers depend on this. Basically, I want to decrease 'bus factor' of the generated wrappers as much as possible. Ideally, I should be able to make build and installation of the wrapped library optional. Related - nim-lang/RFCs#398 and #11

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions