+static inline php_property_proxy_object_t *get_propro(zval *object);
+static inline zval *get_proxied_value(zval *object, zval *return_value);
+static inline void set_proxied_value(zval *object, zval *value);
+
+static zval *read_dimension(zval *object, zval *offset, int type, zval *return_value);
+static ZEND_RESULT_CODE cast_obj(zval *object, zval *return_value, int type);
+static void write_dimension(zval *object, zval *offset, zval *input_value);
+
+#if DEBUG_PROPRO
+/* we do not really care about TS when debugging */
+static int level = 1;
+static const char *inoutstr[] = {"< return","= "," > enter "};
+static const char *types[] = {
+ "UNDEF",
+ "NULL",
+ "FALSE",
+ "TRUE",
+ "int",
+ "float",
+ "string",
+ "Array",
+ "Object",
+ "resource",
+ "reference",
+ "constant",
+ "constant AST",
+ "_BOOL",
+ "callable",
+ "indirect",
+ "---",
+ "pointer"
+};
+
+static int _walk(php_property_proxy_object_t *obj)
+{
+ int p = 0;
+
+ if (obj) {
+ if (!Z_ISUNDEF(obj->parent)) {
+ p += _walk(get_propro(&obj->parent));
+ }
+ if (obj->proxy) {
+ p += fprintf(stderr, ".%s", obj->proxy->member->val);
+ }
+ }
+
+ return p;
+}
+
+static void debug_propro(int inout, const char *f,
+ php_property_proxy_object_t *obj,
+ php_property_proxy_t *proxy,
+ zval *offset, zval *value)
+{
+ int width;
+
+ if (!proxy && obj) {
+ proxy = obj->proxy;
+ }
+
+ fprintf(stderr, "#PP %14p %*c %s %s\t", proxy, level, ' ', inoutstr[inout + 1], f);
+
+ level += inout;
+
+ if (proxy) {
+ fprintf(stderr, " container= %-10p <%12s rc=%d ",
+ Z_REFCOUNTED(proxy->container) ? Z_COUNTED(proxy->container) : NULL,
+ types[Z_TYPE(proxy->container)],
+ Z_REFCOUNTED(proxy->container) ? Z_REFCOUNT(proxy->container) : 0);
+ if (Z_ISREF(proxy->container)) {
+ zval *ref = Z_REFVAL(proxy->container);
+ fprintf(stderr, " %-12s %p rc=% 2d",
+ types[Z_TYPE_P(ref)],
+ ref->value.counted,
+ Z_REFCOUNTED_P(ref) ? Z_REFCOUNT_P(ref) : -1);
+ }
+ fprintf(stderr, "> ");
+ }
+
+ width = _walk(obj);
+
+ if (*f++=='d'
+ && *f++=='i'
+ && *f++=='m'
+ ) {
+ char *offset_str = "[]";
+ zval *o = offset;
+
+ if (o) {
+ convert_to_string_ex(o);
+ offset_str = Z_STRVAL_P(o);
+ }
+
+ width += fprintf(stderr, ".%s", offset_str);
+
+ if (o && o != offset) {
+ zval_ptr_dtor(o);
+ }
+ }
+ if (value) {
+ fprintf(stderr, "%.*s", 32-width, " ");
+ if (Z_ISUNDEF_P(value)) {
+ fprintf(stderr, " =UNDEF ");
+ } else {
+ fprintf(stderr, " = %-10p <%12s rc=%d %3s> ",
+ Z_REFCOUNTED_P(value) ? Z_COUNTED_P(value) : NULL,
+ types[Z_TYPE_P(value)&0xf],
+ Z_REFCOUNTED_P(value) ? Z_REFCOUNT_P(value) : 0,
+ Z_ISREF_P(value) ? "ref" : "");
+ if (!Z_ISUNDEF_P(value) && Z_TYPE_P(value) != IS_INDIRECT) {
+ zend_print_flat_zval_r(value TSRMLS_CC);
+ }
+ }
+ }
+
+ fprintf(stderr, "\n");
+}
+#else
+#define debug_propro(l, f, obj, proxy, off, val)