Original: PHP kernel research and other implementations

Source: Internet
Author: User
Abstract: Original: PHP kernel research and other implementations... these days are busy. I don't have time to write. I have to write more articles over the weekend.
Currently, most languages support classes.
What is a class? Class is object-oriented (OOP). The English name is Object Oriented Programming.
What is object-oriented? Is a programming architecture.
One basic principle of OOP is that a computer program is composed of a single unit or object that can act as a subroutine. OOP achieves three objectives of Software Engineering: reusability, flexibility, and scalability.
This is because we are not talking about the simple description here. if you do not know what a class is or what an object-oriented class is, this article is not suitable for you currently.

ClassPerson {

};

The above is to create a PHP class. class is the keyword of PHP. through it, we can find out how Zend creates a class.


Unticked_class_declaration_statement:

Class_entry_type T_STRING extends_from

{Zend_do_begin_class_declaration (& $1, & $2, & $3 TSRMLS_CC );}

Implements_list

'{'

Class_statement_list

'}' {Zend_do_end_class_declaration (& $1, & $2 TSRMLS_CC );}

| Interface_entry T_STRING

{Zend_do_begin_class_declaration (& $1, & $2, NULL TSRMLS_CC );}

Interface_extends_list

'{'

Class_statement_list

'}' {Zend_do_end_class_declaration (& $1, & $2 TSRMLS_CC );}

;

Class_entry_type:

T_CLASS {$. u. opline_num = CG (zend_lineno); $. u. EA. type = 0 ;}

| T_ABSTRACT T_CLASS {$. u. opline_num = CG (zend_lineno); $. u. EA. type = zend_acc_explicit_policact_class ;}

| T_FINAL T_CLASS {$. u. opline_num = CG (zend_lineno); $. u. EA. type = ZEND_ACC_FINAL_CLASS ;}

;

T_CLASS, T_ABSTRACT T_CLASS, and T_FINAL are three types of PHP patterns.
T_CLASS: a standard class.
T_ABSTRACT: declares an abstract class.
T_FINAL: Declares a class that cannot be inherited or extended.
There are also interfaces.
They are defined in the Zend/zend_complie.h file.

# Define ZEND_ACC_IMPLICIT_ABSTRACT_CLASS 0x10 // The statement is not declared as abstract, but there is an internal abstract method.

# Define ZEND_ACC_EXPLICIT_ABSTRACT_CLASS 0x20 // abstraction

# Define ZEND_ACC_FINAL_CLASS 0x40 // Final

# Define ZEND_ACC_INTERFACE 0x80 // interface

These three rules record the current row and set the class type.
The zend_do_begin_class_declaration and zend_do_end_class_declaration methods are called during class definition,
The class keyword, the class name and the inherited parent class are passed as parameters to these two functions.
Zend_do_begin_class_declaration is used to declare the class, set the type, create
Zend_do_end_class_declaration is used to process attributes and methods in the class.
Before talking about two functions, you must first talk about the structure of the stored class zend_class_entry.
It is defined in Zend/zend. h.


Struct_zend_class_entry {

Chartype;

Char * name; // class name

Zend_uint name_length;

Struct_zend_class_entry * parent; // inherited parent class

Intrefcount; // number of references

Zend_bool constants_updated; // type of the class

Zend_uint ce_flags; // class type abstraction? Interface? Final?

HashTable function_table; // function table

HashTable default_properties; // attribute

HashTable properties_info; // Function access level

HashTable default_static_members; // static member

HashTable * static_members; // static member. when the declared class is default_static_members, the built-in class is NULL.

HashTable constants_table;

Conststruct_zend_function_entry * builtin_functions;

// Are you familiar with it ??? Right. here is the magic function ..

Union_zend_function * constructor;

Union_zend_function * destructor;

Union_zend_function * clone;

Union_zend_function * _ get;

Union_zend_function * _ set;

Union_zend_function * _ unset;

Union_zend_function * _ isset;

Union_zend_function * _ call;

Union_zend_function * _ callstatic;

Union_zend_function * _ tostring;

Union_zend_function * serialize_func;

Union_zend_function * unserialize_func;

Zend_class_iterator_funcs iterator_funcs;

/* Handlers */

Zend_object_value (* create_object) (zend_class_entry * class_type TSRMLS_DC );

Zend_object_iterator * (* get_iterator) (zend_class_entry * ce, zval * object, intby_ref TSRMLS_DC );

Int (* interface_gets_implemented) (zend_class_entry * iface, zend_class_entry * class_type TSRMLS_DC);/* a class implements this interface */

Union_zend_function * (* get_static_method) (zend_class_entry * ce, char * method, intmethod_len TSRMLS_DC );

/* Serializer callbacks */

Int (* serialize) (zval * object, unsignedchar ** buffer, zend_uint * buf_len, zend_serialize_data * data TSRMLS_DC );

Int (* unserialize) (zval ** object, zend_class_entry * ce, constunsignedchar * buf, zend_uint buf_len, zend_unserialize_data * data TSRMLS_DC );

Zend_class_entry ** interfaces;

Zend_uint num_interfaces;

Char * filename; // file address of the declaration class

Zend_uint line_start; // class start line

Zend_uint line_end; // end row of the class

Char * doc_comment;

Zend_uint doc_comment_len;

Struct_zend_module_entry * module;

};

After the structure is clear, let's look at the zend_do_begin_class_declaration function.

Voidzend_do_begin_class_declaration (constznode * class_token, znode * class_name, constznode * parent_class_name TSRMLS_DC )/*{{{*/

{

Zend_op * opline;

Intdoing_inheritance = 0;

Zend_class_entry * new_class_entry;

Char * lcname;

Interror = 0;

Zval ** ns_name;

If (CG (active_class_entry )){

Zend_error (E_COMPILE_ERROR, "Class declarations may not be nested ");

Return;

}

Lcname = zend_str_tolower_dup (class_name-> u. constant. value. str. val, class_name-> u. constant. value. str. len );

If (! (Strcmp (lcname, "self") & strcmp (lcname, "parent "))){

Efree (lcname );

Zend_error (E_COMPILE_ERROR, "Cannot use '% s' as class name as it is reserved", class_name-> u. constant. value. str. val );

}

/* Class name must not conflict with import names */

If (CG (current_import )&&

Zend_hash_find (CG (current_import), lcname, Z_STRLEN (class_name-> u. constant) + 1, (void **) & ns_name) = SUCCESS ){

Error = 1;

}

If (CG (current_namespace )){

/* Prefix class name with name of current namespace */

Znode tmp;

Tmp. u. constant = * CG (current_namespace );

Zval_copy_ctor (& tmp. u. constant );

Zend_do_build_namespace_name (& tmp, & tmp, class_name TSRMLS_CC );

Class_name = & tmp;

Efree (lcname );

Lcname = zend_str_tolower_dup (Z_STRVAL (class_name-> u. constant), Z_STRLEN (class_name-> u. constant ));

}

If (error ){

Char * tmp = zend_str_tolower_dup (Z_STRVAL_PP (ns_name), Z_STRLEN_PP (ns_name ));

If (Z_STRLEN_PP (ns_name )! = Z_STRLEN (class_name-> u. constant) |

Memcmp (tmp, lcname, Z_STRLEN (class_name-> u. constant ))){

Zend_error (E_COMPILE_ERROR, "Cannot declare class % s because the name is already in use", Z_STRVAL (class_name-> u. constant ));

}

Efree (tmp );

}

New_class_entry = emalloc (sizeof (zend_class_entry ));

New_class_entry-> type = ZEND_USER_CLASS;

New_class_entry-> name = class_name-> u. constant. value. str. val;

New_class_entry-> name_length = class_name-> u. constant. value. str. len;

Zend_initialize_class_data (new_class_entry, 1 TSRMLS_CC );

New_class_entry-> filename = zend_get_compiled_filename (TSRMLS_C );

New_class_entry-> line_start = class_token-> u. opline_num;

New_class_entry-> ce_flags | = class_token-> u. EA. type;

If (parent_class_name & parent_class_name-> op_type! = IS_UNUSED ){

Switch (parent_class_name-> u. EA. type ){

CaseZEND_FETCH_CLASS_SELF:

Zend_error (E_COMPILE_ERROR, "Cannot use 'self 'as class name as it is reserved ");

Break;

CaseZEND_FETCH_CLASS_PARENT:

Zend_error (E_COMPILE_ERROR, "Cannot use 'parent' as class name as it is reserved ");

Break;

CaseZEND_FETCH_CLASS_STATIC:

Zend_error (E_COMPILE_ERROR, "Cannot use 'static 'as class name as it is reserved ");

Break;

Default:

Break;

}

Doing_inheritance = 1;

}

Opline = get_next_op (CG (active_op_array) TSRMLS_CC );

Opline-> op1.op _ type = IS_CONST;

Build_runtime_defined_function_key (& opline-> op1.u. constant, lcname, new_class_entry-> name_length TSRMLS_CC );

Opline-> op2.op _ type = IS_CONST;

Opline-> op2.u. constant. type = IS_STRING;

Z_SET_REFCOUNT (opline-> op2.u. constant, 1 );

If (doing_inheritance ){

Opline-> extended_value = parent_class_name-> u. var;

Opline-> opcode = ZEND_DECLARE_INHERITED_CLASS;

} Else {

Opline-> opcode = ZEND_DECLARE_CLASS;

}

Opline-> op2.u. constant. value. str. val = lcname;

Opline-> op2.u. constant. value. str. len = new_class_entry-> name_length;

Zend_hash_update (CG (class_table), opline-> op1.u. constant. value. str. val, opline-> op1.u. constant. value. str. len, & new_class_entry, sizeof (zend_class_entry *), NULL );

CG (active_class_entry) = new_class_entry;

Opline-> result. u. var = get_temporary_variable (CG (active_op_array ));

Opline-> result. op_type = IS_VAR;

CG (implementing_class) = opline-> result;

If (CG (doc_comment )){

CG (active_class_entry)-> doc_comment = CG (doc_comment );

CG (active_class_entry)-> doc_comment_len = CG (doc_comment_len );

CG (doc_comment) = NULL;

CG (doc_comment_len) = 0;

}

}

Lcname = zend_str_tolower_dup (class_name-> u. constant. value. str. val, class_name-> u. constant. value. str. len );
Converts all classes to lowercase. This is why PHP is case insensitive.
If (! (Strcmp (lcname, "self") & strcmp (lcname, "parent "))){
Efree (lcname );
Zend_error (E_COMPILE_ERROR, "Cannot use '% s' as class name as it is reserved", class_name-> u. constant. value. str. val );
}
The class name cannot be self or parent.
Row 23-26 is used to check whether the class name is defined repeatedly.
Line 27-37 is used to set the namespace. this is a new feature of PHP5.3.
Row 39-47 is used to throw an error with repeated definitions.
Row 49-57 initializes the structure of the storage class
Zend_initialize_class_data (new_class_entry, 1 TSRMLS_CC); function is used to initialize HashTable in the structure, magic method.
This function also has the reason (HashTable * static_members; // static member, when the class declared by the user is default_static_members and the built-in class is NULL) mentioned above.
Row 88-73 is also used to check whether the parent class name contains the reserved keywords self, parent, static
The rest is used to generate an OP,
Internal class: the generated OP intermediate code is ZEND_DECLARE_INHERITED_CLASS.
User class: the OP intermediate code is ZEND_DECLARE_CLASS.
After this, the. Zend Engine will call the zend_execute function to execute the intermediate code ZEND_DECLARE_CLASS_SPEC_HANDLER of the OP.
It is defined in Zend/zend_vm_execute.h.
This function will execute key code
EX_T (opline-> result. u. var). class_entry = do_bind_class (opline, EG (class_table), 0 TSRMLS_CC );
Do_bind_class will put this class in class_table. of course, this function will also judge whether the class exists. if it does not exist, an error will be thrown.
Internal Zend error-Missing class information for % s
If yes, it will be added successfully.
The class is successfully created here.
The next section will go deep into the class...

The above is original: PHP kernel research and other implementation content. For more information, see PHP Chinese network (www.php1.cn )!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.