Skip to content

Instantly share code, notes, and snippets.

@kvanbere
Last active January 2, 2016 16:09
Show Gist options
  • Save kvanbere/8328504 to your computer and use it in GitHub Desktop.
Save kvanbere/8328504 to your computer and use it in GitHub Desktop.
typedef void* function_t;
typedef void* prev_closure_t;
union arg_t {
void* box; // Pointer to a boxed thing (or closure)
int val; // Byval if it fits in 8 bytes
};
// foo a b c d e = ...
struct closure_fn_foo {
arg_t a; // all these are zero from the block alloc
arg_t b;
arg_t c;
arg_t d;
arg_t e;
function_t fn; // initialized to a function pointer
prev_closure_t prev; // + sizeof(function_t)
int stack1;
int stack2;
double stack3;
};
// bar x y = ...
struct closure_fn_bar {
arg_t x;
arg_t y;
function_t fn;
prev_closure_t prev; // + sizeof(function_t)
};
// when the compiler can split apply/execute, this fast version can be used
// INLINE this.
void apply_fast(arg_t** closure, arg_t a) {
**closure = a;
*closure++;
}
// INLINE this.
void* execute(arg_t** closure /*, cont_t cont*/ ) {
return **closure(*closure /*, cont*/ );
}
// For polymorphic types or (a -> b)s that can't be resolved at compile time
// INLINE this.
void apply_generic(arg_t** closure, arg_t a) {
**closure = a;
*closure++;
// if not zero by block alloc, we hit a function_t! cheats!
if (*closure) {
execute(closure);
// continuation blah
}
// continuation blah
}
// This is how you would make a PAP and use it
void test() {
void* something;
// The pointer starts at the top of the struct, and we erase the structs original type
// each application move it downwards (simple pointer arith) until we hit the function_t part
// then, the function called with the closure as the argument can access its stack in the positive members
// of the struct use sizeof()s.
void* p = gcalloc(sizeof(closure_fn_foo));
p->fn = some_fn; // set the fn
// in some cases the closure might be linked to a previous lambda environment
// in that case, use linked closures.
p->prev = last_closure;
apply(&p, 1);
apply(&p, something);
// continuation blah
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment