Hello internals,

  sorry the patch got lost somehow, here it is :-)

regards
marcus

Sunday, May 14, 2006, 10:12:12 PM, you wrote:

> Hello guys,

>   after some incantations i came to the attached improved patch that
> allows to give properties any visibility plus mark them as public
> readable. The patch also implements the PHP 6.0 todo item 'readonly
> for overloaded objects'.

> The code now looks like:
> <?php
> class Test {
>   private:public $x = 42;
> }

> $obj = new Test;
> var_dump($obj->x);
?>>

> Note, that this adheres to the following EBNF:

> <property>     := <write_access>+ (':' <read_access>)? '$' <name> ';'
> <write_access> := 'var' | 'public' | 'protected' | 'private'
> <read_access>  := 'public'
> <name>         := [_a-zA_Z][_a-zA_Z0-9]*

> Adding 'protected' to <read_access> is possible to but code wise a
> tiny bit more complex. Chaging the order is of cause also possible.

> best regards
> marcus

> Sunday, May 14, 2006, 11:05:29 AM, you wrote:

>> Hello Jason,

>> Sunday, May 14, 2006, 4:34:03 AM, you wrote:

>>> Hello Marcus,

>>>   class x
>>>   {
>>>      public readonly $xyz;
>>>      protected readonly $abc;
>>>   }

>>>   Definitions:
>>>   - public readonly    - outside class can only read, not write.
>>>   - protected readonly - subclass can only read, not write.
>>>   - private readonly   - does not make sense - do not support.

>>>   How difficult would it be to build this into the PHP engine?

>>> -- 
>>> Best regards,
>>>  Jason                            mailto:[EMAIL PROTECTED]

>>> Saturday, May 13, 2006, 5:27:34 AM, you wrote:

MB>>>> Hello Etienne,

MB>>>> Friday, May 12, 2006, 2:11:38 PM, you wrote:

>>>>> Hi,

>>>>> my 2c:

>>>>> 1) it shouldn't replace the visibility definition: we could also have
>>>>> protected readonly properties.

MB>>>> same here visibility and read/write control are two seperate things.

>>>>> 3) how would you check if the property if readonly ? Trying it could
>>>>> result to a Fatal error as you wanted. You would then need a
>>>>> isReadonly() method/function: the function call wouldn't be spared.

MB>>>> We could add this to reflection api easily.

>> Here's your diff to play around :-)
>> The impact on runtime is a single additional integer check for protected
>> properties and  an additional check for private proeprties where property
>> access would normally fail. For this 5 minute patch i chose the key word
>> 'readonly' as supposed. Actually writing the mail took much longer than
>> brewing the patch and yes i din't care for syntax right now.

>> php -r 'class T{private readonly $x = 42;} $obj = new T; var_dump($obj->x);'
>> int(42)

>> Or readable:

>> <?php
>> class Test {
>>   private readonly $x = 42;
>> }

>> $obj = new Test;
>> var_dump($obj->x);
?>>>

>> As we have the 'Property overloading RFC' on the 6.0 aganda
>> we should probably move part of the stuff to 5.2 already and
>> start with the public read access.

>> http://oss.backendmedia.com/PhP60
>> http://www.zend.com/zend/week/week248.php#Heading3


>> Best regards,
>>  Marcus


> Best regards,
>  Marcus




Best regards,
 Marcus
Index: Zend/zend_compile.h
===================================================================
RCS file: /repository/ZendEngine2/zend_compile.h,v
retrieving revision 1.316.2.8.2.2
diff -u -p -d -r1.316.2.8.2.2 zend_compile.h
--- Zend/zend_compile.h 11 May 2006 21:07:39 -0000      1.316.2.8.2.2
+++ Zend/zend_compile.h 14 May 2006 19:58:11 -0000
@@ -139,6 +139,10 @@ typedef struct _zend_try_catch_element {
 /* deprecation flag */
 #define ZEND_ACC_DEPRECATED 0x40000
 
+/* property handling control */
+#define ZEND_ACC_READ_ONLY  0x080000
+#define ZEND_ACC_PUB_READ   0x100000
+
 char *zend_visibility_string(zend_uint fn_flags);
 
 
Index: Zend/zend_language_parser.y
===================================================================
RCS file: /repository/ZendEngine2/zend_language_parser.y,v
retrieving revision 1.160.2.4.2.1
diff -u -p -d -r1.160.2.4.2.1 zend_language_parser.y
--- Zend/zend_language_parser.y 11 May 2006 21:07:39 -0000      1.160.2.4.2.1
+++ Zend/zend_language_parser.y 14 May 2006 19:58:12 -0000
@@ -500,8 +500,9 @@ method_body:
 ;
 
 variable_modifiers:
-               non_empty_member_modifiers              { $$ = $1; }
-       |       T_VAR                                                   { 
Z_LVAL($$.u.constant) = ZEND_ACC_PUBLIC; }
+               non_empty_member_modifiers                              { $$ = 
$1; }
+       |       non_empty_member_modifiers ':' T_PUBLIC { $$ = $1; 
Z_LVAL($$.u.constant) |= ZEND_ACC_PUB_READ; }
+       |       T_VAR                                                           
        { Z_LVAL($$.u.constant) = ZEND_ACC_PUBLIC; }
 ;
 
 method_modifiers:
Index: Zend/zend_object_handlers.c
===================================================================
RCS file: /repository/ZendEngine2/zend_object_handlers.c,v
retrieving revision 1.135.2.6.2.2
diff -u -p -d -r1.135.2.6.2.2 zend_object_handlers.c
--- Zend/zend_object_handlers.c 10 May 2006 21:12:48 -0000      1.135.2.6.2.2
+++ Zend/zend_object_handlers.c 14 May 2006 19:58:12 -0000
@@ -144,20 +144,26 @@ static zval *zend_std_call_issetter(zval
        return retval;
 }
 
-static int zend_verify_property_access(zend_property_info *property_info, 
zend_class_entry *ce TSRMLS_DC)
+static int zend_verify_property_access(zend_property_info *property_info, 
zend_class_entry *ce, int read_write TSRMLS_DC)
 {
+       if (!read_write && (property_info->flags & ZEND_ACC_READ_ONLY)) {
+               return 0;
+       }
        switch (property_info->flags & ZEND_ACC_PPP_MASK) {
                case ZEND_ACC_PUBLIC:
                        return 1;
                case ZEND_ACC_PROTECTED:
-                       return zend_check_protected(ce, EG(scope));
+                       if ((property_info->flags & ZEND_ACC_PUB_READ) && 
read_write) {
+                               return 1;
+                       } else {
+                               return zend_check_protected(ce, EG(scope));
+                       }
                case ZEND_ACC_PRIVATE:
-                       if (ce==EG(scope) && EG(scope)) {
+                       if ((ce == EG(scope) && ce) || ((property_info->flags & 
ZEND_ACC_PUB_READ) && read_write)) {
                                return 1;
                        } else {
                                return 0;
                        }
-                       break;
        }
        return 0;
 }
@@ -175,7 +181,7 @@ static inline zend_bool is_derived_class
        return 0;
 }
 
-ZEND_API struct _zend_property_info *zend_get_property_info(zend_class_entry 
*ce, zval *member, int silent TSRMLS_DC)
+ZEND_API struct _zend_property_info 
*zend_get_property_info_ex(zend_class_entry *ce, zval *member, int silent, int 
read_write TSRMLS_DC)
 {
        zend_property_info *property_info = NULL;
        zend_property_info *scope_property_info;
@@ -198,7 +204,7 @@ ZEND_API struct _zend_property_info *zen
                        /* if it's a shadow - go to access it's private */
                        property_info = NULL;
                } else {
-                       if (zend_verify_property_access(property_info, ce 
TSRMLS_CC)) {
+                       if (zend_verify_property_access(property_info, ce, 
read_write TSRMLS_CC)) {
                                if (property_info->flags & ZEND_ACC_CHANGED
                                        && !(property_info->flags & 
ZEND_ACC_PRIVATE)) {
                                        /* We still need to make sure that 
we're not in a context
@@ -244,6 +250,11 @@ ZEND_API struct _zend_property_info *zen
 }
 
 
+ZEND_API struct _zend_property_info *zend_get_property_info(zend_class_entry 
*ce, zval *member, int silent TSRMLS_DC)
+{
+       return zend_get_property_info_ex(ce, member, silent, 0 TSRMLS_CC);
+}
+
 ZEND_API int zend_check_property_access(zend_object *zobj, char 
*prop_info_name TSRMLS_DC)
 {
        zend_property_info *property_info;
@@ -252,7 +263,7 @@ ZEND_API int zend_check_property_access(
 
        zend_unmangle_property_name(prop_info_name, &class_name, &prop_name);
        ZVAL_STRING(&member, prop_name, 0);
-       property_info = zend_get_property_info(zobj->ce, &member, 1 TSRMLS_CC);
+       property_info = zend_get_property_info_ex(zobj->ce, &member, 1, 0 
TSRMLS_CC);
        if (!property_info) {
                return FAILURE;
        }
@@ -265,7 +276,7 @@ ZEND_API int zend_check_property_access(
                        return FAILURE;
                }
        }
-       return zend_verify_property_access(property_info, zobj->ce TSRMLS_CC) ? 
SUCCESS : FAILURE;
+       return zend_verify_property_access(property_info, zobj->ce, 1 
TSRMLS_CC) ? SUCCESS : FAILURE;
 }
 
 static int zend_get_property_guard(zend_object *zobj, zend_property_info 
*property_info, zval *member, zend_guard **pguard)
@@ -318,7 +329,7 @@ zval *zend_std_read_property(zval *objec
 #endif                 
 
        /* make zend_get_property_info silent if we have getter - we may want 
to use it */
-       property_info = zend_get_property_info(zobj->ce, member, 
(zobj->ce->__get != NULL) TSRMLS_CC);
+       property_info = zend_get_property_info_ex(zobj->ce, member, 
(zobj->ce->__get != NULL), 1 TSRMLS_CC);
 
        if (!property_info || zend_hash_quick_find(zobj->properties, 
property_info->name, property_info->name_length+1, property_info->h, (void **) 
&retval) == FAILURE) {
                zend_guard *guard;
@@ -371,7 +382,7 @@ static void zend_std_write_property(zval
                member = tmp_member;
        }
 
-       property_info = zend_get_property_info(zobj->ce, member, 
(zobj->ce->__set != NULL) TSRMLS_CC);
+       property_info = zend_get_property_info_ex(zobj->ce, member, 
(zobj->ce->__set != NULL), 0 TSRMLS_CC);
 
        if (property_info && zend_hash_quick_find(zobj->properties, 
property_info->name, property_info->name_length+1, property_info->h, (void **) 
&variable_ptr) == SUCCESS) {
                if (*variable_ptr == value) {
@@ -526,7 +537,7 @@ static zval **zend_std_get_property_ptr_
        fprintf(stderr, "Ptr object #%d property: %s\n", 
Z_OBJ_HANDLE_P(object), Z_STRVAL_P(member));
 #endif
 
-       property_info = zend_get_property_info(zobj->ce, member, 
(zobj->ce->__get != NULL) TSRMLS_CC);
+       property_info = zend_get_property_info_ex(zobj->ce, member, 
(zobj->ce->__get != NULL), 0 TSRMLS_CC);
 
        if (!property_info || zend_hash_quick_find(zobj->properties, 
property_info->name, property_info->name_length+1, property_info->h, (void **) 
&retval) == FAILURE) {
                zval *new_zval;
@@ -570,7 +581,7 @@ static void zend_std_unset_property(zval
                member = tmp_member;
        }
 
-       property_info = zend_get_property_info(zobj->ce, member, 
(zobj->ce->__unset != NULL) TSRMLS_CC);
+       property_info = zend_get_property_info_ex(zobj->ce, member, 
(zobj->ce->__unset != NULL), 0 TSRMLS_CC);
 
        if (!property_info || zend_hash_del(zobj->properties, 
property_info->name, property_info->name_length+1) == FAILURE) {
                zend_guard *guard;
@@ -849,7 +860,7 @@ ZEND_API zval **zend_std_get_static_prop
        zend_printf("Access type for %s::%s is %s\n", ce->name, property_name, 
zend_visibility_string(property_info->flags));
 #endif
 
-       if (!zend_verify_property_access(property_info, ce TSRMLS_CC)) {
+       if (!zend_verify_property_access(property_info, ce, 1 TSRMLS_CC)) {
                if (!silent) {
                        zend_error(E_ERROR, "Cannot access %s property 
%s::$%s", zend_visibility_string(property_info->flags), ce->name, 
property_name);
                }
@@ -945,7 +956,7 @@ static int zend_std_has_property(zval *o
        fprintf(stderr, "Read object #%d property: %s\n", 
Z_OBJ_HANDLE_P(object), Z_STRVAL_P(member));
 #endif
 
-       property_info = zend_get_property_info(zobj->ce, member, 1 TSRMLS_CC);
+       property_info = zend_get_property_info_ex(zobj->ce, member, 1, 0 
TSRMLS_CC);
 
        if (!property_info || zend_hash_quick_find(zobj->properties, 
property_info->name, property_info->name_length+1, property_info->h, (void **) 
&value) == FAILURE) {
                zend_guard *guard;
Index: Zend/zend_object_handlers.h
===================================================================
RCS file: /repository/ZendEngine2/zend_object_handlers.h,v
retrieving revision 1.47.2.2.2.1
diff -u -p -d -r1.47.2.2.2.1 zend_object_handlers.h
--- Zend/zend_object_handlers.h 9 May 2006 23:53:23 -0000       1.47.2.2.2.1
+++ Zend/zend_object_handlers.h 14 May 2006 19:58:12 -0000
@@ -140,6 +140,7 @@ BEGIN_EXTERN_C()
 ZEND_API union _zend_function *zend_std_get_static_method(zend_class_entry 
*ce, char *function_name_strval, int function_name_strlen TSRMLS_DC);
 ZEND_API zval **zend_std_get_static_property(zend_class_entry *ce, char 
*property_name, int property_name_len, zend_bool silent TSRMLS_DC);
 ZEND_API zend_bool zend_std_unset_static_property(zend_class_entry *ce, char 
*property_name, int property_name_len TSRMLS_DC);
+ZEND_API struct _zend_property_info 
*zend_get_property_info_ex(zend_class_entry *ce, zval *member, int silent, int 
read_write TSRMLS_DC);
 ZEND_API struct _zend_property_info *zend_get_property_info(zend_class_entry 
*ce, zval *member, int silent TSRMLS_DC);
 
 ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int 
type TSRMLS_DC);
-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to