+void psi_context_compile(struct psi_context *C)
+{
+ psi_context_consts_init(C);
+ psi_context_extvars_init(C);
+ psi_context_impls_init(C);
+ psi_context_decls_init(C);
+
+ /* zend_register_functions depends on EG(current_module) pointing into module */
+ EG(current_module) = zend_hash_str_find_ptr(&module_registry, "psi", sizeof("psi") - 1);
+ if (SUCCESS != zend_register_functions(NULL, C->closures, NULL, MODULE_PERSISTENT)) {
+ C->error(PSI_DATA(C), NULL, PSI_WARNING, "Failed to register functions!");
+ }
+ EG(current_module) = NULL;
+}
+
+ZEND_RESULT_CODE psi_context_call(struct psi_context *C, zend_execute_data *execute_data, zval *return_value, struct psi_impl *impl)
+{
+ struct psi_call_frame *frame;
+
+ frame = psi_call_frame_init(C, impl->decl, impl);
+
+ if (SUCCESS != psi_call_frame_parse_args(frame, execute_data)) {
+ psi_call_frame_free(frame);
+
+ return FAILURE;
+ }
+
+ psi_call_frame_enter(frame);
+
+ if (SUCCESS != psi_call_frame_do_let(frame)) {
+ psi_call_frame_do_return(frame, return_value);
+ psi_call_frame_free(frame);
+
+ return FAILURE;
+ }
+
+ if (SUCCESS != psi_call_frame_do_assert(frame, PSI_ASSERT_PRE)) {
+ psi_call_frame_do_return(frame, return_value);
+ psi_call_frame_free(frame);
+
+ return FAILURE;
+ }
+
+ if (psi_call_frame_num_var_args(frame)) {
+ C->ops->call_va(frame);
+ } else {
+ C->ops->call(frame);
+ }
+
+ if (SUCCESS != psi_call_frame_do_assert(frame, PSI_ASSERT_POST)) {
+ psi_call_frame_do_return(frame, return_value);
+ psi_call_frame_free(frame);
+
+ return FAILURE;
+ }
+
+ psi_call_frame_do_return(frame, return_value);
+ psi_call_frame_do_set(frame);
+ psi_call_frame_do_free(frame);
+ psi_call_frame_free(frame);
+
+ return SUCCESS;
+}
+
+
+void psi_context_dtor(struct psi_context *C)
+{
+ size_t i;
+ zend_function_entry *zfe;
+
+ if (C->decls) {
+ size_t i = 0;
+ struct psi_decl *decl;
+
+ while (psi_plist_get(C->decls, i++, &decl)) {
+ size_t j = 0;
+ struct psi_decl_arg *darg;
+
+ while (psi_plist_get(decl->args, j++, &darg)) {
+ C->ops->composite_dtor(C, darg);
+ }
+ C->ops->composite_dtor(C, decl->func);
+ C->ops->decl_dtor(C, decl);
+ }
+
+ }
+ if (C->vars) {
+ size_t i = 0;
+ struct psi_decl_extvar *evar;
+
+ while (psi_plist_get(C->vars, i++, &evar)) {
+ C->ops->composite_dtor(C, evar->getter->func);
+ C->ops->composite_dtor(C, evar->arg);
+ C->ops->extvar_dtor(C, evar);
+ }
+ }
+ if (C->impls) {
+ size_t i = 0;
+ struct psi_impl *impl;
+
+ while (psi_plist_get(C->impls, i++, &impl)) {
+ struct psi_let_stmt *let;
+ size_t j = 0;
+
+ while (psi_plist_get(impl->stmts.let, j++, &let)) {
+ psi_context_callback_dtor(C, let->exp, impl);
+ }
+
+ C->ops->impl_dtor(C, impl);
+ }
+ }
+
+ if (C->ops->dtor) {
+ C->ops->dtor(C);
+ }
+
+ psi_data_dtor(PSI_DATA(C));
+
+ if (C->data) {
+ for (i = 0; i < C->count; ++i) {
+ psi_data_dtor(&C->data[i]);
+ }
+ free(C->data);
+ }
+
+ if (C->closures) {
+ for (zfe = C->closures; zfe->fname; ++zfe) {
+ pefree((void *) zfe->arg_info, 1);
+ }
+ pefree(C->closures, 1);
+ }
+}
+
+void psi_context_free(struct psi_context **C)