calc: boolean expressions
[m6w6/ext-psi] / src / marshal.c
1 /*******************************************************************************
2 Copyright (c) 2016, Michael Wallner <mike@php.net>.
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7
8 * Redistributions of source code must retain the above copyright notice,
9 this list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13
14 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
18 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *******************************************************************************/
25
26 #include "php_psi_stdinc.h"
27 #include "data.h"
28 #include "calc.h"
29
30 #include "php.h"
31 #include "php_psi.h"
32
33 #include "Zend/zend_interfaces.h"
34 #include "ext/spl/spl_iterators.h"
35
36 zend_long psi_zval_count(zval *zvalue)
37 {
38 /* mimic PHP count() */
39 zend_long count;
40 zval retval;
41
42 switch (Z_TYPE_P(zvalue)) {
43 default:
44 count = 1;
45 break;
46 case IS_NULL:
47 count = 0;
48 break;
49 case IS_ARRAY:
50 count = zend_array_count(Z_ARRVAL_P(zvalue));
51 break;
52 case IS_OBJECT:
53 count = 1;
54 if (Z_OBJ_HT_P(zvalue)->count_elements) {
55 if (SUCCESS == Z_OBJ_HT_P(zvalue)->count_elements(zvalue, &count)) {
56 break;
57 }
58 }
59
60 if (instanceof_function(Z_OBJCE_P(zvalue), spl_ce_Countable)) {
61 zend_call_method_with_0_params(zvalue, NULL, NULL, "count", &retval);
62 if (Z_TYPE(retval) != IS_UNDEF) {
63 count = zval_get_long(&retval);
64 zval_ptr_dtor(&retval);
65 }
66 }
67 break;
68 }
69
70 return count;
71 }
72
73 int psi_internal_type(struct psi_impl_type *type)
74 {
75 switch (type->type) {
76 case PSI_T_BOOL:
77 return _IS_BOOL;
78 case PSI_T_INT:
79 return IS_LONG;
80 case PSI_T_FLOAT:
81 case PSI_T_DOUBLE:
82 return IS_DOUBLE;
83 case PSI_T_STRING:
84 return IS_STRING;
85 case PSI_T_ARRAY:
86 return IS_ARRAY;
87 default:
88 return 0;
89 }
90 }
91
92 zend_internal_arg_info *psi_internal_arginfo(struct psi_impl *impl)
93 {
94 size_t i = 0, argc = psi_plist_count(impl->func->args);
95 zend_internal_arg_info *aip;
96 zend_internal_function_info *fi;
97 struct psi_impl_arg *iarg;
98
99 aip = calloc(argc + 1 + !!impl->func->vararg, sizeof(*aip));
100
101 fi = (zend_internal_function_info *) &aip[0];
102 fi->type = ZEND_TYPE_ENCODE(psi_internal_type(impl->func->return_type), 1);
103 fi->required_num_args = psi_impl_num_min_args(impl);
104 fi->return_reference = impl->func->return_reference;
105
106 if (impl->func->vararg) {
107 struct psi_impl_arg *vararg = impl->func->vararg;
108 zend_internal_arg_info *ai = &aip[argc];
109
110 ai->name = vararg->var->name;
111 ai->type = ZEND_TYPE_ENCODE(psi_internal_type(vararg->type), 1);
112 if (vararg->var->reference) {
113 ai->pass_by_reference = 1;
114 }
115 ai->is_variadic = 1;
116 }
117
118 while (psi_plist_get(impl->func->args, i++, &iarg)) {
119 zend_internal_arg_info *ai = &aip[i];
120
121 ai->name = iarg->var->name;
122 ai->type = ZEND_TYPE_ENCODE(psi_internal_type(iarg->type), 1);
123 if (iarg->var->reference) {
124 ai->pass_by_reference = 1;
125 }
126 }
127
128 return aip;
129 }
130
131 /*
132 * return void(dvar)
133 */
134 void psi_set_void(zval *return_value, struct psi_set_exp *set, impl_val *ret_val, struct psi_call_frame *frame)
135 {
136 RETVAL_NULL();
137 }
138
139 /*
140 * ?
141 */
142 impl_val *psi_let_void(impl_val *tmp, struct psi_decl_type *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free)
143 {
144 return tmp;
145 }
146
147 /*
148 * set $ivar = zval(dvar)
149 */
150 void psi_set_zval(zval *return_value, struct psi_set_exp *set, impl_val *ret_val, struct psi_call_frame *frame) {
151 RETVAL_ZVAL(ret_val->ptr, 1, 0);
152 }
153
154 /*
155 * let dvar = zval($ivar)
156 */
157 impl_val *psi_let_zval(impl_val *tmp, struct psi_decl_type *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free)
158 {
159 *to_free = tmp->ptr = emalloc(sizeof(zval));
160 ZVAL_COPY_VALUE(tmp->ptr, zvalue);
161 return tmp;
162 }
163
164 /*
165 * return to_bool(dvar)
166 */
167 void psi_set_to_bool(zval *return_value, struct psi_set_exp *set, impl_val *ret_val, struct psi_call_frame *frame)
168 {
169 psi_set_to_int(return_value, set, ret_val, frame);
170 convert_to_boolean(return_value);
171 }
172
173 static inline impl_val *psi_val_boolval(impl_val *tmp, token_t real_type, zend_bool boolval) {
174 switch (real_type) {
175 case PSI_T_INT8: tmp->i8 = boolval; break;
176 case PSI_T_UINT8: tmp->u8 = boolval; break;
177 case PSI_T_INT16: tmp->i16 = boolval; break;
178 case PSI_T_UINT16: tmp->u16 = boolval; break;
179 case PSI_T_INT32: tmp->i32 = boolval; break;
180 case PSI_T_UINT32: tmp->u32 = boolval; break;
181 case PSI_T_INT64: tmp->i64 = boolval; break;
182 case PSI_T_UINT64: tmp->u64 = boolval; break;
183 case PSI_T_FLOAT: tmp->fval = boolval; break;
184 case PSI_T_DOUBLE: tmp->dval = boolval; break;
185 #ifdef HAVE_LONG_DOUBLE
186 case PSI_T_LONG_DOUBLE: tmp->ldval = boolval; break;
187 #endif
188 EMPTY_SWITCH_DEFAULT_CASE();
189 }
190 return tmp;
191 }
192
193 /*
194 * let dvar = boolval($ivar)
195 */
196 impl_val *psi_let_boolval(impl_val *tmp, struct psi_decl_type *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free)
197 {
198 zend_bool boolval;
199 token_t real_type = spec ? psi_decl_type_get_real(spec)->type : PSI_T_UINT8;
200
201 if (ival && impl_type == PSI_T_BOOL) {
202 boolval = ival->zend.bval;
203 } else {
204 boolval = zend_is_true(zvalue);
205 }
206
207 return psi_val_boolval(tmp, real_type, boolval);
208 }
209
210 # define RETVAL_LONG_U64(V) \
211 if (V > ZEND_LONG_MAX) { \
212 char d[24] = {0}; \
213 RETVAL_STRING(zend_print_ulong_to_buf(&d[22], V)); \
214 } else { \
215 RETVAL_LONG(V); \
216 }
217
218 /*
219 * set $ivar = to_int(*dvar)
220 */
221 void psi_set_to_int(zval *return_value, struct psi_set_exp *set, impl_val *ret_val, struct psi_call_frame *frame)
222 {
223 struct psi_decl_var *var = psi_set_exp_get_decl_var(set);
224 token_t t = psi_decl_type_get_real(var->arg->type)->type;
225 impl_val *v = deref_impl_val(ret_val, var);
226
227 switch (t) {
228 case PSI_T_INT8: RETVAL_LONG(v->i8); break;
229 case PSI_T_UINT8: RETVAL_LONG(v->u8); break;
230 case PSI_T_INT16: RETVAL_LONG(v->i16); break;
231 case PSI_T_UINT16: RETVAL_LONG(v->u16); break;
232 case PSI_T_INT32: RETVAL_LONG(v->i32); break;
233 case PSI_T_UINT32: RETVAL_LONG(v->u32); break;
234 case PSI_T_INT64: RETVAL_LONG(v->i64); break;
235 case PSI_T_UINT64: RETVAL_LONG_U64(v->u64); break;
236 case PSI_T_FLOAT: RETVAL_DOUBLE((double) v->fval); break;
237 case PSI_T_DOUBLE: RETVAL_DOUBLE(v->dval); break;
238 #ifdef HAVE_LONG_DOUBLE
239 case PSI_T_LONG_DOUBLE: RETVAL_DOUBLE((double) v->ldval); break;
240 #endif
241 EMPTY_SWITCH_DEFAULT_CASE();
242 }
243
244 convert_to_long(return_value);
245 }
246
247 static inline impl_val *psi_val_intval(impl_val *tmp, token_t real_type, zend_long intval) {
248 switch (real_type) {
249 case PSI_T_INT8: tmp->i8 = intval; break;
250 case PSI_T_UINT8: tmp->u8 = intval; break;
251 case PSI_T_INT16: tmp->i16 = intval; break;
252 case PSI_T_UINT16: tmp->u16 = intval; break;
253 case PSI_T_INT32: tmp->i32 = intval; break;
254 case PSI_T_UINT32: tmp->u32 = intval; break;
255 case PSI_T_INT64: tmp->i64 = intval; break;
256 case PSI_T_UINT64: tmp->u64 = intval; break;
257 case PSI_T_INT: tmp->ival = intval; break;
258 case PSI_T_LONG: tmp->lval = intval; break;
259 case PSI_T_FLOAT: tmp->fval = intval; break;
260 case PSI_T_DOUBLE: tmp->dval = intval; break;
261 #ifdef HAVE_LONG_DOUBLE
262 case PSI_T_LONG_DOUBLE: tmp->ldval = intval; break;
263 #endif
264 EMPTY_SWITCH_DEFAULT_CASE();
265 }
266
267 return tmp;
268 }
269
270 /*
271 * let dvar = intval($ivar)
272 */
273 impl_val *psi_let_intval(impl_val *tmp, struct psi_decl_type *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free)
274 {
275 zend_long intval;
276 token_t real_type = spec ? psi_decl_type_get_real(spec)->type : PSI_T_LONG;
277
278 if (ival && impl_type == PSI_T_INT) {
279 intval = ival->zend.lval;
280 } else {
281 intval = zval_get_long(zvalue);
282 }
283
284 return psi_val_intval(tmp, real_type, intval);
285 }
286
287 /*
288 * set $ivar = to_float(dvar)
289 */
290 void psi_set_to_float(zval *return_value, struct psi_set_exp *set, impl_val *ret_val, struct psi_call_frame *frame)
291 {
292 struct psi_decl_var *var = psi_set_exp_get_decl_var(set);
293 token_t t = psi_decl_type_get_real(var->arg->type)->type;
294 impl_val *v = deref_impl_val(ret_val, var);
295
296 switch (t) {
297 case PSI_T_FLOAT: RETVAL_DOUBLE((double) v->fval); break;
298 case PSI_T_DOUBLE: RETVAL_DOUBLE(v->dval); break;
299 #ifdef HAVE_LONG_DOUBLE
300 case PSI_T_LONG_DOUBLE: RETVAL_DOUBLE((double) v->ldval); break;
301 #endif
302 case PSI_T_INT8: RETVAL_DOUBLE((double) v->i8); break;
303 case PSI_T_UINT8: RETVAL_DOUBLE((double) v->u8); break;
304 case PSI_T_INT16: RETVAL_DOUBLE((double) v->i16); break;
305 case PSI_T_UINT16: RETVAL_DOUBLE((double) v->u16); break;
306 case PSI_T_INT32: RETVAL_DOUBLE((double) v->i32); break;
307 case PSI_T_UINT32: RETVAL_DOUBLE((double) v->u32); break;
308 case PSI_T_INT64: RETVAL_DOUBLE((double) v->i64); break;
309 case PSI_T_UINT64: RETVAL_DOUBLE((double) v->u64); break;
310 EMPTY_SWITCH_DEFAULT_CASE();
311 }
312 }
313
314 static inline impl_val *psi_val_floatval(impl_val *tmp, token_t real_type, double floatval) {
315 switch (real_type) {
316 case PSI_T_INT8: tmp->i8 = floatval; break;
317 case PSI_T_UINT8: tmp->u8 = floatval; break;
318 case PSI_T_INT16: tmp->i16 = floatval; break;
319 case PSI_T_UINT16: tmp->u16 = floatval; break;
320 case PSI_T_INT32: tmp->i32 = floatval; break;
321 case PSI_T_UINT32: tmp->u32 = floatval; break;
322 case PSI_T_INT64: tmp->i64 = floatval; break;
323 case PSI_T_UINT64: tmp->u64 = floatval; break;
324 case PSI_T_FLOAT: tmp->fval = floatval; break;
325 case PSI_T_DOUBLE: tmp->dval = floatval; break;
326 #ifdef HAVE_LONG_DOUBLE
327 case PSI_T_LONG_DOUBLE: tmp->ldval = floatval; break;
328 #endif
329 EMPTY_SWITCH_DEFAULT_CASE();
330 }
331
332 return tmp;
333 }
334
335 /*
336 * let dvar = floatval($ivar)
337 */
338 impl_val *psi_let_floatval(impl_val *tmp, struct psi_decl_type *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free)
339 {
340 double floatval;
341 token_t real_type = spec ? psi_decl_type_get_real(spec)->type : PSI_T_DOUBLE;
342
343 if (ival && (impl_type == PSI_T_FLOAT || impl_type == PSI_T_DOUBLE)) {
344 floatval = ival->dval;
345 } else {
346 floatval = zval_get_double(zvalue);
347 }
348
349 return psi_val_floatval(tmp, real_type, floatval);
350 }
351
352 /*
353 * set $ivar = to_string(dvar)
354 */
355 void psi_set_to_string(zval *return_value, struct psi_set_exp *set, impl_val *ret_val, struct psi_call_frame *frame)
356 {
357 struct psi_decl_var *var = psi_set_exp_get_decl_var(set);
358 impl_val *ptr = deref_impl_val(ret_val, var);
359 char *str;
360
361 if (var->arg->var->array_size) {
362 str = (char *) ptr;
363 } else {
364 str = ptr->ptr;
365 }
366
367 if (str) {
368 RETVAL_STRING(str);
369 } else {
370 RETVAL_EMPTY_STRING();
371 }
372 }
373
374 /*
375 * set $ivar = to_string(dvar, num_exp)
376 */
377 void psi_set_to_stringl(zval *return_value, struct psi_set_exp *set, impl_val *ret_val, struct psi_call_frame *frame)
378 {
379 struct psi_decl_var *var = psi_set_exp_get_decl_var(set);
380 char *str = deref_impl_val(ret_val, var)->ptr;
381
382 if (str) {
383 struct psi_set_exp *sub_exp;
384
385 psi_plist_get(set->inner, 0, &sub_exp);
386 RETVAL_STRINGL(str, psi_long_num_exp(sub_exp->data.num, frame));
387 } else {
388 RETVAL_EMPTY_STRING();
389 }
390 }
391
392 /*
393 * let dvar = strval($ivar)
394 */
395 impl_val *psi_let_strval(impl_val *tmp, struct psi_decl_type *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free)
396 {
397 if (ival && impl_type == PSI_T_STRING) {
398 if (ival->zend.str) {
399 tmp->ptr = ival->zend.str->val;
400 } else {
401 tmp->ptr = "";
402 }
403 } else {
404 zend_string *zs = zval_get_string(zvalue);
405 tmp->ptr = estrdup(zs->val);
406 *to_free = tmp->ptr;
407 zend_string_release(zs);
408 }
409
410 return tmp;
411 }
412
413 /*
414 * let dvar = pathval($ivar)
415 */
416 impl_val *psi_let_pathval(impl_val *tmp, struct psi_decl_type *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free)
417 {
418 tmp = psi_let_strval(tmp, spec, impl_type, ival, zvalue, to_free);
419 if (SUCCESS != php_check_open_basedir(tmp->ptr)) {
420 efree(tmp->ptr);
421 tmp->ptr = NULL;
422 return *to_free = NULL;
423 }
424 return tmp;
425 }
426
427 /*
428 * let dvar = strlen($ivar)
429 */
430 impl_val *psi_let_strlen(impl_val *tmp, struct psi_decl_type *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free)
431 {
432 if (ival && impl_type == PSI_T_STRING) {
433 if (ival->zend.str) {
434 tmp->lval = ival->zend.str->len;
435 } else {
436 tmp->lval = 0;
437 }
438 } else {
439 zend_string *zs = zval_get_string(zvalue);
440 tmp->lval = zs->len;
441 zend_string_release(zs);
442 }
443
444 return tmp;
445 }
446
447 static impl_val *iterate(impl_val *val, size_t size, unsigned i, impl_val *tmp)
448 {
449 memset(tmp, 0, sizeof(*tmp));
450 memcpy(tmp, ((char *) val) + size * i, size);
451 return tmp;
452 }
453
454 /*
455 * set $ivar = to_array(dvar,
456 * $foo = to_int(d_foo),
457 * $bar = to_string(d_bar),
458 * $baz = to_array(*d_next, ...)
459 */
460 void psi_set_to_recursive(zval *return_value, struct psi_set_exp *set, impl_val *r_val, struct psi_call_frame *frame) {
461 set->outer->data.func->handler(return_value, set, r_val, frame);
462 }
463
464 /*
465 * set $ivar = to_array(dvar, to_string(*dvar));
466 */
467 void psi_set_to_array_simple(zval *return_value, struct psi_set_exp *set, impl_val *r_val, struct psi_call_frame *frame)
468 {
469 struct psi_set_exp *sub_exp;
470 struct psi_decl_var *var;
471 impl_val *ret_val;
472 char *ptr;
473 size_t size;
474
475 array_init(return_value);
476
477 var = psi_set_exp_get_decl_var(set);
478 ret_val = deref_impl_val(r_val, var);
479 if ((intptr_t) ret_val <= (intptr_t) 0) {
480 return;
481 }
482
483 psi_plist_get(set->inner, 0, &sub_exp);
484
485 size = psi_decl_arg_get_size(var->arg);
486 for (ptr = ret_val->ptr; *(void **) ptr; ptr += size) {
487 zval ele;
488
489 ZVAL_NULL(&ele);
490 sub_exp->data.func->handler(&ele, sub_exp, (void *) ptr, frame);
491 add_next_index_zval(return_value, &ele);
492 }
493 }
494
495 /*
496 * set $ivar = to_array(dvar, num_exp, to_string(*dvar));
497 */
498 void psi_set_to_array_counted(zval *return_value, struct psi_set_exp *set, impl_val *r_val, struct psi_call_frame *frame)
499 {
500 struct psi_set_exp *sub_exp;
501 struct psi_decl_var *var;
502 impl_val *ret_val;
503 char *ptr;
504 size_t size;
505 zend_long count;
506
507 array_init(return_value);
508
509 var = psi_set_exp_get_decl_var(set);
510 ret_val = deref_impl_val(r_val, var);
511 if ((intptr_t) ret_val <= (intptr_t) 0) {
512 return;
513 }
514
515 psi_plist_get(set->inner, 0, &sub_exp);
516 count = psi_long_num_exp(sub_exp->data.num, frame);
517 psi_plist_get(set->inner, 1, &sub_exp);
518
519 for (ptr = (char *) ret_val; 0 < count--; ptr += size) {
520 size = psi_decl_var_get_size(psi_set_exp_get_decl_var(sub_exp));
521 zval ele;
522
523 ZVAL_NULL(&ele);
524 sub_exp->data.func->handler(&ele, sub_exp, (void *) &ptr, frame);
525 add_next_index_zval(return_value, &ele);
526 }
527 }
528
529 #include "call.h"
530
531 /*
532 * set $ivar = to_array(dvar,
533 * $foo = to_int(d_foo),
534 * $bar = to_string(d_bar));
535 */
536 void psi_set_to_array(zval *return_value, struct psi_set_exp *set, impl_val *r_val, struct psi_call_frame *frame)
537 {
538 struct psi_set_exp *sub_exp;
539 struct psi_decl_var *var;
540 impl_val *ret_val;
541 size_t i = 0;
542
543 array_init(return_value);
544
545 var = psi_set_exp_get_decl_var(set);
546 ret_val = deref_impl_val(r_val, var);
547 if ((intptr_t) ret_val <= (intptr_t) 0) {
548 return;
549 }
550
551 while (psi_plist_get(set->inner, i++, &sub_exp)) {
552 zval ele;
553 struct psi_decl_var *dvar = psi_set_exp_get_decl_var(sub_exp);
554 struct psi_impl_var *ivar = psi_set_exp_get_impl_var(sub_exp);
555 struct psi_call_frame_symbol *sym;
556
557 sym = psi_call_frame_fetch_symbol(frame, dvar);
558 sym->ptr = ((char *) ret_val) + dvar->arg->layout->pos;
559
560 ZVAL_NULL(&ele);
561 psi_set_exp_exec_ex(sub_exp, &ele, sym->ptr, frame);
562 add_assoc_zval(return_value, ivar->name + 1, &ele);
563 }
564 }
565
566 //impl_val *psi_let_arrval(impl_val *tmp, decl_type *spec, decl_var *spec_var, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free)
567 //{
568 // decl_type *real = real_decl_type(spec);
569 // HashTable *arr;
570 // zval *zv;
571 // size_t i, sz;
572 // decl_arg tmp_arg = {0};
573 //
574 // if (impl_type != PSI_T_ARRAY) {
575 // SEPARATE_ARG_IF_REF(zvalue);
576 // convert_to_array(zvalue);
577 // }
578 // arr = HASH_OF(zvalue);
579 //
580 // switch (real->type) {
581 // case PSI_T_STRUCT:
582 // *to_free = tmp = psi_array_to_struct(real->real.strct, arr);
583 // break;
584 // case PSI_T_UNION:
585 // *to_free = tmp = psi_array_to_union(real->real.unn, arr);
586 // break;
587 // default:
588 // sz = psi_t_size(real->type);
589 // tmp = *to_free = ecalloc(zend_hash_num_elements(arr), sz);
590 // tmp_arg.type = spec;
591 // tmp_arg.var = spec_var;
592 // ZEND_HASH_FOREACH_VAL_IND(arr, zv)
593 // {
594 // void *ptr = ((char *) tmp) + (i++ * sz);
595 // psi_from_zval_ex(NULL, (impl_val **) &ptr, &tmp_arg, 0, zv, NULL);
596 // }
597 // ZEND_HASH_FOREACH_END();
598 // }
599 //
600 // return tmp;
601 //}
602
603 /*
604 * let dvar = count($ivar)
605 */
606 impl_val *psi_let_count(impl_val *tmp, struct psi_decl_type *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free)
607 {
608 return psi_val_intval(tmp, psi_decl_type_get_real(spec)->type, psi_zval_count(zvalue));
609 }
610
611 /*
612 * set $ivar = to_object(dvar)
613 */
614 void psi_set_to_object(zval *return_value, struct psi_set_exp *set, impl_val *r_val, struct psi_call_frame *frame)
615 {
616 struct psi_decl_var *var = psi_set_exp_get_decl_var(set);
617 impl_val *ret_val = deref_impl_val(r_val, var);
618
619 if ((intptr_t) ret_val->ptr > (intptr_t) 0) {
620 object_init_ex(return_value, psi_object_get_class_entry());
621 PSI_OBJ(return_value, NULL)->data = ret_val->ptr;
622 } else {
623 RETVAL_NULL();
624 }
625 }
626
627 /*
628 * let dvar = objval($ivar)
629 */
630 impl_val *psi_let_objval(impl_val *tmp, struct psi_decl_type *spec, token_t impl_type, impl_val *ival, zval *zvalue, void **to_free)
631 {
632 psi_object *obj;
633
634 if (Z_TYPE_P(zvalue) != IS_OBJECT
635 || !instanceof_function(Z_OBJCE_P(zvalue), psi_object_get_class_entry())) {
636 return NULL;
637 }
638
639 obj = PSI_OBJ(zvalue, NULL);
640 tmp->ptr = obj->data;
641
642 return tmp;
643 }
644