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