+ ZEND_PARSE_PARAMETERS_END_EX(return FAILURE);
+
+ return SUCCESS;
+}
+
+static impl_val *handle_let(decl_arg *darg, impl_arg *iarg) {
+ impl_val *arg_val = &darg->let->out;
+
+ if (!iarg) {
+ /* let foo = NULL */
+ memset(arg_val, 0, sizeof(*arg_val));
+ return arg_val;
+ }
+ switch (darg->let->val->func->type) {
+ case PSI_T_BOOLVAL:
+ if (iarg->type->type == PSI_T_BOOL) {
+ arg_val->cval = iarg->val.cval;
+ } else {
+ arg_val->cval = zend_is_true(iarg->_zv);
+ }
+ break;
+ case PSI_T_INTVAL:
+ if (iarg->type->type == PSI_T_INT) {
+ arg_val->lval = iarg->val.lval;
+ } else {
+ arg_val->lval = zval_get_long(iarg->_zv);
+ }
+ break;
+ case PSI_T_STRVAL:
+ if (iarg->type->type == PSI_T_STRING) {
+ arg_val->ptr = estrdup(iarg->val.str->val);
+ darg->let->mem = arg_val->ptr;
+ zend_string_release(iarg->val.str);
+ } else {
+ zend_string *zs = zval_get_string(iarg->_zv);
+ arg_val->ptr = estrdup(zs->val);
+ darg->let->mem = arg_val->ptr;
+ zend_string_release(zs);
+ }
+ break;
+ case PSI_T_STRLEN:
+ if (iarg->type->type == PSI_T_STRING) {
+ arg_val->lval = iarg->val.str->len;
+ zend_string_release(iarg->val.str);
+ } else {
+ zend_string *zs = zval_get_string(iarg->_zv);
+ arg_val->lval = zs->len;
+ zend_string_release(zs);
+ }
+ break;
+ EMPTY_SWITCH_DEFAULT_CASE();
+ }
+
+ return arg_val;
+}
+
+static void handle_rval(impl *impl, impl_val *ret_val, zval *return_value) {
+ switch (impl->stmts->ret.list[0]->func->type) {
+ case PSI_T_TO_STRING:
+ to_string(ret_val, impl->decl->func, return_value);
+ break;
+ case PSI_T_TO_INT:
+ to_int(ret_val, impl->decl->func, return_value);
+ break;
+ EMPTY_SWITCH_DEFAULT_CASE();
+ }
+}
+
+static void handle_set(zval *return_value, set_func *func, decl_vars *vars) {
+ impl_val *val = &vars->vars[0]->arg->let->ptr;
+
+ zval_dtor(return_value);
+
+ switch (func->type) {
+ case PSI_T_TO_STRING:
+ to_string(val, vars->vars[0]->arg, return_value);
+ break;
+ EMPTY_SWITCH_DEFAULT_CASE();
+ }
+}
+
+static void handle_free(free_stmt *fre) {
+ size_t i;
+
+ for (i = 0; i < fre->vars->count; ++i) {
+ decl_var *dvar = fre->vars->vars[i];
+
+ if (dvar->arg && dvar->arg->let->out.ptr) {
+ free(dvar->arg->let->out.ptr);
+ dvar->arg->let->out.ptr = NULL;
+ }
+ }
+}
+
+static void handler(jit_type_t _sig, void *result, void **_args, void *_data)
+{
+ PSI_ClosureData *data = _data;
+ size_t i;
+ void **arg_ptr = NULL, **arg_prm = NULL;
+ impl_val ret_val;
+
+ if (SUCCESS != handle_args(*(zend_execute_data **)_args[0], data->impl)) {
+ return;
+ }