Skip to content

Conversation

@GlowingScrewdriver
Copy link
Contributor

This is an effort to automate the process of generating bindings to libraries using their C header files. Parsing and resolving types is offloaded to Clang/LLVM, while gen_bindings.py maps LLVM types to C-Lisp types and exposes the binding generation machinery via C-Lisp macros.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move this to src/backend

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@chsasank
Copy link
Owner

Fix #95

@chsasank
Copy link
Owner

Great work so far. See how zig does it: https://ziglang.org/learn/overview/#integration-with-c-libraries-without-ffibindings. Namespacing would be useful. If we can do that, we can ditch explicit naming of all the functions, typedefs etc.

(c-lisp
,@(include
(shape.h)
()
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like this syntax that much because of empty lists and non named stuff

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right. I'm open to writing a new macro that wraps this macro, takes no arguments and includes all available functions + structs they depend on.
Available functions can be scraped from the JSON AST.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although the ability to have unspecified arguments is an important capability. So maybe we could implement keyword arguments in Prelisp?
Perhaps something like this, in sexp:

,(macro-fn parg1 (parg2_1 parg2_2) ((karg1 . val1) (karg2 . val2)))

and equivalent Python call would be

macro_fn("parg1", ["parg2_1" "parg2-2"], karg1="val1", karg2="val2")

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's look up the syntax for lisp for named arguments and copy it!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright, Guile supports keyword arguments, so we can use that.

; Procedure definition
(define* (func #:key arg)
    arg)

; Procedure call
(display (func #:arg 'value))

result:

value

Although there are a lot of Scheme implementations (including Guile) that support some form of keyword arguments, the Scheme spec doesn't provide keyword arguments.

Copy link
Contributor Author

@GlowingScrewdriver GlowingScrewdriver Nov 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only issue here is that guile-json doesn't seem to be able to handle it. When the following call is passed through sexp-json.scm,

(define ((main int))
    ,(func 'pos-arg-val #:kw-arg-val)

    (ret 0))

the following error is thrown:

json/builder.scm:189:9: In procedure json-valid?:
Throw to key `json-invalid' with args `(#:kw-arg-val)'.

So we'll have to write our own logic in sexp-json.scm to handle keyword arguments in macro calls.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

try reading the this using (read) first and then see how it works. It's possible it's just a symbol?

,(error_check (call cuDeviceGetCount (ptr-to devCount)))
,(error_check (call cuDeviceGet (ptr-to device) 0))
,(error_check (call cuCtxCreate (ptr-to context) 0 device))
,(error_check (call cuCtxCreate_v2 (ptr-to context) 0 device))
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why does this have to _v2?

Copy link
Contributor Author

@GlowingScrewdriver GlowingScrewdriver Aug 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cuCtxCreate happens to be a macro. And macros won't show up in the JSON AST :/

So with the current framework it's not possible to infer what cuCtxCreate is supposed to be

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, the issue is a little more complicated than that. It's defined both as a macro and as a function:

// ...
#define cuCtxCreate                         cuCtxCreate_v2
// ...
CUresult CUDAAPI cuCtxCreate(CUcontext *pctx, unsigned int flags, CUdevice dev);
// ...

As far as I can see, neither definition is within a conditional (e.g. #if, #ifdef) block.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This commit introduces the following changes:

* Keyword arguments can now be specified in macro
  calls like this:
  `,(macro_func (#:kwarg val))`

  This is equivalent to the following Python call:
  `macro_func (kwarg=val)`

* The following tests:
  + parser/keyword.sexp -- Handling JSON serialization of keywords
  + prelisp/kwargs.sexp -- Passing keyword arguments to macros
  + prelisp/errors/invalid-keyword.sexp -- Error test
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

Successfully merging this pull request may close these issues.

2 participants