+#define DEBUG_PROPRO 1
+
+static inline php_property_proxy_object_t *get_propro(zval *object);
+static zval *get_parent_proxied_value(zval *object, zval *return_value);
+static zval *get_proxied_value(zval *object, zval *return_value);
+static 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_proxied_value(zval *object, zval *return_value, int type);
+static void write_dimension(zval *object, zval *offset, zval *value);
+
+#if DEBUG_PROPRO
+/* we do not really care about TS when debugging */
+static int level = 1;
+static const char space[] = " ";
+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 void _walk(php_property_proxy_object_t *obj)
+{
+ if (obj) {
+ if (!Z_ISUNDEF(obj->parent)) {
+ _walk(get_propro(&obj->parent));
+ }
+ if (obj->proxy) {
+ fprintf(stderr, ".%s", obj->proxy->member->val);
+ }
+ }
+}
+
+static void debug_propro(int inout, const char *f,
+ php_property_proxy_object_t *obj,
+ php_property_proxy_t *proxy,
+ zval *offset, zval *value)
+{
+ if (!proxy && obj) {
+ proxy = obj->proxy;
+ }
+
+ fprintf(stderr, "#PP %p (%p) %s %s %s ",
+ proxy,
+ proxy->container.value.counted,
+ &space[sizeof(space)-level],
+ inoutstr[inout+1], f);
+
+ level += inout;
+
+ _walk(obj);