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 <[email protected]> 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 <[email protected]> wrote:
>> On Sat, Mar 13, 2010 at 3:13 PM, Moriyoshi Koizumi <[email protected]> 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