pure-c / purec

C backend for PureScript
233 stars 8 forks source link

Explore not using Blocks for scopes #5

Closed felixSchl closed 6 years ago

felixSchl commented 6 years ago

Currently we rely on a clang extension called "Blocks" contributed to the compiler project by Apple that essentially gives us closures in C. It would be interesting to see if we can go without this extension in order to be able to compile without clang and to avoid the blocks runtime.

It should be possible to - at compile time - inspect each function's scope, create a struct for it, and model functions like this:

f x =
  let r y =
   in x
typedef (const purs_any_t *) (* purs_fun_fn) (const void * ctx, const purs_any_t * arg);
typedef struct purs_fun {
  const void * ctx;
  purs_fun_fn fn;
} purs_fun_t;
typedef struct f_ctx { /* empty */ } f_ctx_t; // just NULL?
typedef struct f_r_ctx { const purs_any_t * x } f_r_ctx_t;
purs_any_t * f (const void * ctx, const purs_any_t * x) {
  const f_ctx_t * f_ctx = (const f_ctx_t *) f_ctx;
  purs_any_t * out = GC_NEW(purs_any_t);
  purs_fun_t * fun = GC_NEW(purs_fun_t);
  f_r_ctx * f_r_ctx = GC_NEW(f_r_ctx);
  f_r_ctx->x = x;
  fun->fn = f_r;
  fun->ctx = f_r_ctx;
  out->tag = FUNCTION;
  out->value.fn = fun;
  return (const purs_any_t *) out;
}
felixSchl commented 6 years ago

I am not sure if this is desirable now. Having blocks makes writing curried FFI functions a breeze and the overhead (apart from losing compiler compatibility) is negligible from what I can tell.

felixSchl commented 6 years ago

An alternative, however, could be revisiting to use C++ for the closures feature alone, and otherwise pretend we're in C. That should keep the simplicity and perhaps improve on compatibility with different compiler toolchains.

felixSchl commented 6 years ago

Implemented!