It looks like I stripped off too much. Attached is the right one.

Moriyoshi

On Sun, Mar 14, 2010 at 12:41 AM, Moriyoshi Koizumi <m...@mozo.jp> wrote:
> Surprisingly, It can be done quite easily with the current object
> handler infrastructure.
>
> Moriyoshi
>
> On Sun, Mar 14, 2010 at 12:08 AM, Pierre Joye <pierre....@gmail.com> wrote:
>> On Sat, Mar 13, 2010 at 3:13 PM, Moriyoshi Koizumi <m...@mozo.jp> wrote:
>>
>>> I don't totally agree with what is being said here, but I guess we
>>> don't have to make Unicode a first-class value.  Once operator
>>> overloading is supported, Unicode strings can be represented as
>>> objects, like Python does although  I didn't have a look at past
>>> discussion on this topic.
>>
>> Operators overloading, while being a cool feature, should not be
>> associated with Unicode&related features. Or we are going to do the
>> exact same mistakes than before, way too many changes, features, work
>> to even get a visible deadline for the next major release.
>>
>> Cheers,
>> --
>> Pierre
>>
>> @pierrejoye | http://blog.thepimp.net | http://www.libgd.org
>>
>
diff --git a/Zend/zend.h b/Zend/zend.h
index 38f461c..0ffcb1a 100644
--- a/Zend/zend.h
+++ b/Zend/zend.h
@@ -442,6 +442,7 @@ struct _zend_class_entry {
        union _zend_function *__call;
        union _zend_function *__callstatic;
        union _zend_function *__tostring;
+       union _zend_function *__concat;
        union _zend_function *serialize_func;
        union _zend_function *unserialize_func;
 
diff --git a/Zend/zend_API.c b/Zend/zend_API.c
index 5433dc1..e0dcd73 100644
--- a/Zend/zend_API.c
+++ b/Zend/zend_API.c
@@ -1799,7 +1799,7 @@ ZEND_API int zend_register_functions(zend_class_entry 
*scope, const zend_functio
        int count=0, unload=0;
        HashTable *target_function_table = function_table;
        int error_type;
-       zend_function *ctor = NULL, *dtor = NULL, *clone = NULL, *__get = NULL, 
*__set = NULL, *__unset = NULL, *__isset = NULL, *__call = NULL, *__callstatic 
= NULL, *__tostring = NULL;
+       zend_function *ctor = NULL, *dtor = NULL, *clone = NULL, *__get = NULL, 
*__set = NULL, *__unset = NULL, *__isset = NULL, *__call = NULL, *__callstatic 
= NULL, *__tostring = NULL, *__concat = NULL;
        char *lowercase_name;
        int fname_len;
        char *lc_class_name = NULL;
@@ -1929,6 +1929,8 @@ ZEND_API int zend_register_functions(zend_class_entry 
*scope, const zend_functio
                                __unset = reg_function;
                        } else if ((fname_len == 
sizeof(ZEND_ISSET_FUNC_NAME)-1) && !memcmp(lowercase_name, 
ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME))) {
                                __isset = reg_function;
+                       } else if ((fname_len == 
sizeof(ZEND_CONCAT_FUNC_NAME)-1) && !memcmp(lowercase_name, 
ZEND_CONCAT_FUNC_NAME, sizeof(ZEND_CONCAT_FUNC_NAME))) {
+                               __concat = reg_function;
                        } else {
                                reg_function = NULL;
                        }
@@ -1967,6 +1969,7 @@ ZEND_API int zend_register_functions(zend_class_entry 
*scope, const zend_functio
                scope->__set = __set;
                scope->__unset = __unset;
                scope->__isset = __isset;
+               scope->__concat = __concat;
                if (ctor) {
                        ctor->common.fn_flags |= ZEND_ACC_CTOR;
                        if (ctor->common.fn_flags & ZEND_ACC_STATIC) {
@@ -2030,6 +2033,12 @@ ZEND_API int zend_register_functions(zend_class_entry 
*scope, const zend_functio
                        }
                        __isset->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
                }
+               if (__concat) {
+                       if (__concat->common.fn_flags & ZEND_ACC_STATIC) {
+                               zend_error(error_type, "Method %s::%s() cannot 
be static", scope->name, __concat->common.function_name);
+                       }
+                       __concat->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
+               }
                efree(lc_class_name);
        }
        return SUCCESS;
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 13b6c55..91cd34a 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -1267,6 +1267,10 @@ void zend_do_begin_function_declaration(znode 
*function_token, znode *function_n
                        } else if ((name_len == 
sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_TOSTRING_FUNC_NAME, 
sizeof(ZEND_TOSTRING_FUNC_NAME)-1))) {
                                if (fn_flags & ((ZEND_ACC_PPP_MASK | 
ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
                                        zend_error(E_WARNING, "The magic method 
__toString() must have public visibility and cannot be static");
+                }
+                       } else if ((name_len == 
sizeof(ZEND_CONCAT_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CONCAT_FUNC_NAME, 
sizeof(ZEND_CONCAT_FUNC_NAME)-1))) {
+                               if (fn_flags & ((ZEND_ACC_PPP_MASK | 
ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
+                                       zend_error(E_WARNING, "The magic method 
" ZEND_CONCAT_FUNC_NAME " must have public visibility and cannot be static");
                                }
                        }
                } else {
@@ -1335,6 +1339,11 @@ void zend_do_begin_function_declaration(znode 
*function_token, znode *function_n
                                        zend_error(E_WARNING, "The magic method 
__toString() must have public visibility and cannot be static");
                                }                               
                                CG(active_class_entry)->__tostring = 
(zend_function *) CG(active_op_array);
+                       } else if ((name_len == 
sizeof(ZEND_CONCAT_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CONCAT_FUNC_NAME, 
sizeof(ZEND_CONCAT_FUNC_NAME)-1))) {
+                               if (fn_flags & ((ZEND_ACC_PPP_MASK | 
ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
+                                       zend_error(E_WARNING, "The magic method 
" ZEND_CONCAT_FUNC_NAME " must have public visibility and cannot be static");
+                               }                               
+                               CG(active_class_entry)->__concat = 
(zend_function *) CG(active_op_array);
                        } else if (!(fn_flags & ZEND_ACC_STATIC)) {
                                CG(active_op_array)->fn_flags |= 
ZEND_ACC_ALLOW_STATIC;
                        }
diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h
index faff1ec..0656883 100644
--- a/Zend/zend_compile.h
+++ b/Zend/zend_compile.h
@@ -745,6 +745,7 @@ END_EXTERN_C()
 #define ZEND_CALLSTATIC_FUNC_NAME   "__callstatic"
 #define ZEND_TOSTRING_FUNC_NAME     "__tostring"
 #define ZEND_AUTOLOAD_FUNC_NAME     "__autoload"
+#define ZEND_CONCAT_FUNC_NAME          "__concat"
 
 /* The following constants may be combined in CG(compiler_options)
  * to change the default compiler behavior */
diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c
index 1424a11..29a5ca1 100644
--- a/Zend/zend_object_handlers.c
+++ b/Zend/zend_object_handlers.c
@@ -1290,6 +1290,31 @@ ZEND_API int zend_std_cast_object_tostring(zval 
*readobj, zval *writeobj, int ty
 }
 /* }}} */
 
+ZEND_API int zend_std_concat_op(zval *obj, zval *result, zval *rhs TSRMLS_DC) 
/* {{{ */
+{
+       zval *retval;
+       zend_class_entry *ce = Z_OBJCE_P(obj);
+       if (ce->__concat && (zend_call_method_with_1_params(&obj, ce, 
&ce->__concat, ZEND_CONCAT_FUNC_NAME, &retval, rhs) || EG(exception))) {
+               if (EG(exception)) {
+                       if (retval) {
+                               zval_ptr_dtor(&retval);
+                       }
+                       zend_error(E_ERROR, "Method %s::" ZEND_CONCAT_FUNC_NAME 
"() must not throw an exception", ce->name);
+                       return FAILURE;
+               }
+               if (Z_TYPE_P(retval) == IS_NULL) {
+                       zval_ptr_dtor(&retval);
+                       return FAILURE;
+               } else {
+                       ZVAL_ZVAL(result, retval, 1, 1);
+                       return SUCCESS;
+               }
+       }
+       return FAILURE;
+}
+/* }}} */
+
+
 int zend_std_get_closure(zval *obj, zend_class_entry **ce_ptr, zend_function 
**fptr_ptr, zval **zobj_ptr TSRMLS_DC) /* {{{ */
 {
        zend_class_entry *ce;
@@ -1344,6 +1369,7 @@ ZEND_API zend_object_handlers std_object_handlers = {
        NULL,                                                                   
/* count_elements */
        NULL,                                                                   
/* get_debug_info */
        zend_std_get_closure,                                   /* get_closure 
*/
+    zend_std_concat_op                                         /* concat_op */
 };
 
 /*
diff --git a/Zend/zend_object_handlers.h b/Zend/zend_object_handlers.h
index 34f4e02..5e73ef7 100644
--- a/Zend/zend_object_handlers.h
+++ b/Zend/zend_object_handlers.h
@@ -110,6 +110,8 @@ typedef int (*zend_object_count_elements_t)(zval *object, 
long *count TSRMLS_DC)
 
 typedef int (*zend_object_get_closure_t)(zval *obj, zend_class_entry **ce_ptr, 
union _zend_function **fptr_ptr, zval **zobj_ptr TSRMLS_DC);
 
+typedef int (*zend_object_concat_op_t)(zval *obj, zval *result, zval *rhs 
TSRMLS_DC);
+
 struct _zend_object_handlers {
        /* general object functions */
        zend_object_add_ref_t                                   add_ref;
@@ -138,6 +140,7 @@ struct _zend_object_handlers {
        zend_object_count_elements_t                    count_elements;
        zend_object_get_debug_info_t                    get_debug_info;
        zend_object_get_closure_t                               get_closure;
+       zend_object_concat_op_t                                 concat_op;
 };
 
 extern ZEND_API zend_object_handlers std_object_handlers;
@@ -151,6 +154,7 @@ ZEND_API struct _zend_property_info 
*zend_get_property_info(zend_class_entry *ce
 ZEND_API HashTable *zend_std_get_properties(zval *object TSRMLS_DC);
 ZEND_API HashTable *zend_std_get_debug_info(zval *object, int *is_temp 
TSRMLS_DC);
 ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int 
type TSRMLS_DC);
+ZEND_API int zend_std_concat_op(zval *obj, zval *result, zval *rhs TSRMLS_DC);
 
 
 #define IS_ZEND_STD_OBJECT(z)  (Z_TYPE(z) == IS_OBJECT && 
(Z_OBJ_HT((z))->get_class_entry != NULL))
diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c
index 8af1ede..154002c 100644
--- a/Zend/zend_operators.c
+++ b/Zend/zend_operators.c
@@ -1205,6 +1205,11 @@ ZEND_API int concat_function(zval *result, zval *op1, 
zval *op2 TSRMLS_DC) /* {{
        zval op1_copy, op2_copy;
        int use_copy1 = 0, use_copy2 = 0;
 
+       if (Z_TYPE_P(op1) == IS_OBJECT && Z_OBJ_HT_P(op1)->concat_op) {
+               if (SUCCESS == Z_OBJ_HT_P(op1)->concat_op(op1, result, op2 
TSRMLS_CC)) {
+                       return SUCCESS;
+               }
+       }
        if (Z_TYPE_P(op1) != IS_STRING) {
                zend_make_printable_zval(op1, &op1_copy, &use_copy1);
        }
-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to