+
+ if (darg_members && func->inner) {
+ /* struct or union
+ * arrval($foo,
+ * str = strval($str),
+ * num = intval($num));
+ */
+ size_t i = 0, size;
+ struct psi_let_exp *inner;
+ struct psi_decl_arg *darg_member;
+
+ val->var->pointer_level += val->is_reference;
+ size = psi_decl_var_get_size(val->var);
+ container = ecalloc(1, size);
+ val->var->pointer_level -= val->is_reference;
+
+ if (frame_arg->zval_ptr) {
+ while (psi_plist_get(func->inner, i++, &inner)) {
+ zend_string *var_name = psi_let_exp_get_decl_var_name(inner);
+ darg_member = psi_decl_arg_get_by_name(darg_members, var_name);
+
+ exec_let_func_arrval_inner(func, darg, darg_member, frame_arg,
+ inner, container, frame);
+ zend_string_release(var_name);
+ }
+ }
+ } else if (func->inner) {
+ /* array
+ * arrval($foo, foo = intval($foo))
+ */
+ size_t arcount;
+ struct psi_let_exp *inner;
+
+ if (!frame_arg->zval_ptr) {
+ return NULL;
+ }
+ assert(psi_plist_count(func->inner) == 1);
+
+ arcount = zend_array_count(Z_ARRVAL_P(frame_arg->zval_ptr));
+ psi_plist_get(func->inner, 0, &inner);
+
+ inner->var->pointer_level += inner->is_reference;
+ container = ecalloc(arcount + 1, psi_decl_var_get_size(inner->var));
+ inner->var->pointer_level -= inner->is_reference;
+
+ exec_let_func_arrval_seq(func, darg, frame_arg, inner, container, frame);
+ } else {
+ assert(0);
+ }
+
+ return *psi_call_frame_push_auto(frame, container);
+}
+
+void *psi_let_func_exec(struct psi_let_exp *val, struct psi_let_func *func,
+ struct psi_decl_arg *darg, struct psi_call_frame *frame)
+{
+ struct psi_call_frame_symbol *frame_sym;
+ psi_marshal_let let_fn = locate_let_func_fn(func->type);
+
+ frame_sym = psi_call_frame_fetch_symbol(frame, val->var);
+
+ if (let_fn) {
+ void *temp = NULL;
+ struct psi_call_frame_argument *iarg;
+
+ iarg = psi_call_frame_get_argument(frame, func->var->fqn);
+
+ assert(iarg);
+
+ frame_sym->ival_ptr = let_fn(&frame_sym->temp_val, darg,
+ iarg->spec ? iarg->spec->type->type : 0, iarg->ival_ptr,
+ iarg->zval_ptr, &temp);
+ if (temp) {
+ psi_call_frame_push_auto(frame, temp);
+ }
+ } else if (func->type == PSI_T_ARRVAL) {
+ frame_sym->ival_ptr = exec_let_func_arrval(val, func, darg, frame);
+ }
+
+ return frame_sym->ival_ptr;