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

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

Open
1 of 10 tasks
Tracked by #5
haxscramper opened this issue Oct 6, 2021 · 1 comment
Open
1 of 10 tasks
Tracked by #5
Labels

Comments

@haxscramper
Copy link
Owner

haxscramper commented Oct 6, 2021


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

@haxscramper haxscramper changed the title Configuration for more sophisticated wrapper logic Automatically generate boilerplate code that makes wrappers easier to use Oct 13, 2021
@haxscramper haxscramper added the enhancement New feature or request label Oct 13, 2021
haxscramper added a commit that referenced this issue Oct 18, 2021
@haxscramper haxscramper pinned this issue Oct 29, 2021
@haxscramper
Copy link
Owner Author

haxscramper commented Nov 3, 2021

Make wrapper analyze build environment to provide necessary information for a wrapper to function properly or fail

  • checking the existence of a C define - conditionally enable sections of the wrapper-generated code. Requires Wrapping macro and conditional compilation semantics #21 to be implemented, probably need to make a different structure for the IR.
  • checking the existence of a C function/variable
  • interface with pkg-config to obtain dependency data - maybe some other package managers.
  • interface for user to supply dependency data via config/command-line
  • ability to define a wrapping function with a tag of the library it needs, which is then searched automatically by the library and specified for linking
  • some sort of ABI verification tooling so that Nim wrapped struct == C struct - related generate completeStruct annotations when possible #7
  • nice error message to tell user how to get the library - better than codegen or linker errors.

Directly related - nim-lang/RFCs#414

Technically I'm aiming to produce a wrapper, not drag the whole build system together with me, so #20 is related

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

No branches or pull requests

1 participant