+static inline struct psi_ffi_impl_info *psi_ffi_impl_init(struct psi_impl *impl,
+ struct psi_context *C) {
+ struct psi_ffi_context *context = C->context;
+ struct psi_ffi_impl_info *info = calloc(1, sizeof(*info));
+ struct psi_let_stmt *let;
+ ffi_status rc;
+ size_t l = 0;
+
+ info->context = C;
+
+ rc = psi_ffi_prep_closure(&info->closure, &info->code,
+ &context->signature, psi_ffi_handler, impl);
+
+ if (FFI_OK != rc) {
+ free(info);
+ return NULL;
+ }
+
+ while (psi_plist_get(impl->stmts.let, l++, &let)) {
+ psi_ffi_callback_init(info, let->exp);
+ }
+
+ return impl->info = info;
+}
+
+static inline void psi_ffi_impl_dtor(struct psi_impl *impl) {
+ struct psi_ffi_impl_info *info = impl->info;
+ struct psi_let_stmt *let;
+ size_t j = 0;
+
+ while (psi_plist_get(impl->stmts.let, j++, &let)) {
+ psi_ffi_callback_dtor(let->exp);
+ }
+
+ if (info) {
+ if (info->closure) {
+ psi_ffi_closure_free(info->closure);
+ }
+ free(info);
+ impl->info = NULL;
+ }
+}
+
+
+static inline struct psi_ffi_context *psi_ffi_context_init(struct psi_ffi_context *L) {
+ ffi_status rc;
+
+ if (!L) {
+ L = malloc(sizeof(*L));
+ }
+ memset(L, 0, sizeof(*L));
+
+ L->params[0] = &ffi_type_pointer;
+ L->params[1] = &ffi_type_pointer;
+ rc = ffi_prep_cif(&L->signature, FFI_DEFAULT_ABI, 2, &ffi_type_void, L->params);
+ assert(rc == FFI_OK);
+
+ return L;
+}
+
+static inline void psi_ffi_context_free(struct psi_ffi_context **L) {
+ if (*L) {
+ free(*L);
+ *L = NULL;
+ }
+}
+
+static void psi_ffi_init(struct psi_context *C)
+{
+ C->context = psi_ffi_context_init(NULL);
+}
+
+static void psi_ffi_dtor(struct psi_context *C)
+{
+ if (C->decls) {
+ size_t i = 0;
+ struct psi_decl *decl;
+
+ while (psi_plist_get(C->decls, i++, &decl)) {
+ psi_ffi_decl_dtor(decl);
+ }
+
+ }
+ if (C->impls) {
+ size_t i = 0;
+ struct psi_impl *impl;
+
+ while (psi_plist_get(C->impls, i++, &impl)) {
+ psi_ffi_impl_dtor(impl);
+ }
+ }
+ psi_ffi_context_free((void *) &C->context);
+}
+
+