diff options
author | Andi Gutmans <andi@php.net> | 2002-03-02 20:38:52 +0000 |
---|---|---|
committer | Andi Gutmans <andi@php.net> | 2002-03-02 20:38:52 +0000 |
commit | b90d80b58806083ded586da0745f02b38d301819 (patch) | |
tree | 052b205bd3fb76749def1abdfd3094fd022279aa /Zend | |
parent | bc7e0b55121755e35e1a659e1d82822e3b7fcde8 (diff) | |
download | php-git-b90d80b58806083ded586da0745f02b38d301819.tar.gz |
- Initial patch to support importing from class scopes (for Stig).
- It isn't complete yet but I want to work on it from another machine. It
- shouldn't break anything else so just don't try and use it.
- The following is a teaser of something that already works:
<?php
class MyClass
{
function hello()
{
print "Hello, World\n";
}
class MyClass2
{
function hello()
{
print "Hello, World in MyClass2\n";
}
}
}
import function hello, class MyClass2 from MyClass;
MyClass2::hello();
hello();
?>
Diffstat (limited to 'Zend')
-rw-r--r-- | Zend/zend_compile.c | 54 | ||||
-rw-r--r-- | Zend/zend_compile.h | 22 | ||||
-rw-r--r-- | Zend/zend_execute.c | 61 | ||||
-rw-r--r-- | Zend/zend_globals.h | 2 | ||||
-rw-r--r-- | Zend/zend_language_parser.y | 30 | ||||
-rw-r--r-- | Zend/zend_language_scanner.l | 8 |
6 files changed, 166 insertions, 11 deletions
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 33216efa87..997848d350 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -552,6 +552,60 @@ zend_bool zend_is_function_or_method_call(znode *variable) return ((type & ZEND_PARSED_METHOD_CALL) || (type == ZEND_PARSED_FUNCTION_CALL)); } +void zend_do_begin_import(TSRMLS_D) +{ + zend_llist_init(&CG(import_commands), sizeof(zend_op), NULL, 0); +} + +void zend_do_import(int type, znode *what TSRMLS_DC) +{ + zend_op opline; + + init_op(&opline TSRMLS_CC); + + switch (type) { + case T_FUNCTION: + opline.opcode = ZEND_IMPORT_FUNCTION; + break; + case T_CLASS: + opline.opcode = ZEND_IMPORT_CLASS; + break; + case T_CONST: + opline.opcode = ZEND_IMPORT_CONST; + break; + } + + if (what) { + if (type == T_FUNCTION || type == T_CLASS) { + zend_str_tolower(what->u.constant.value.str.val, what->u.constant.value.str.len); + } + opline.op2 = *what; + } else { + SET_UNUSED(opline.op2); + } + + zend_llist_add_element(&CG(import_commands), &opline); +} + +void zend_do_end_import(znode *import_from TSRMLS_DC) +{ + zend_llist_element *le; + zend_op *opline, *opline_ptr; + + + le = CG(import_commands).head; + + while (le) { + opline_ptr = (zend_op *)le->data; + opline = get_next_op(CG(active_op_array) TSRMLS_CC); + memcpy(opline, opline_ptr, sizeof(zend_op)); + opline->op1 = *import_from; + le = le->next; + } + zend_llist_destroy(&CG(import_commands)); +} + + void zend_do_begin_variable_parse(TSRMLS_D) { diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index aa2043a938..4b00f5727b 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -366,6 +366,10 @@ void zend_do_extended_fcall_end(TSRMLS_D); void zend_do_ticks(TSRMLS_D); +void zend_do_begin_import(TSRMLS_D); +void zend_do_import(int type, znode *what TSRMLS_DC); +void zend_do_end_import(znode *import_from TSRMLS_DC); + ZEND_API void function_add_ref(zend_function *function); #define INITIAL_OP_ARRAY_SIZE 64 @@ -540,16 +544,20 @@ int zendlex(znode *zendlval TSRMLS_DC); #define ZEND_CATCH 107 #define ZEND_THROW 108 -#define ZEND_FETCH_CLASS 110 +#define ZEND_FETCH_CLASS 109 + +#define ZEND_CLONE 110 -#define ZEND_CLONE 111 +#define ZEND_INIT_CTOR_CALL 111 +#define ZEND_INIT_METHOD_CALL 112 +#define ZEND_INIT_STATIC_METHOD_CALL 113 -#define ZEND_INIT_CTOR_CALL 112 -#define ZEND_INIT_METHOD_CALL 113 -#define ZEND_INIT_STATIC_METHOD_CALL 114 +#define ZEND_ISSET_ISEMPTY_VAR 114 +#define ZEND_ISSET_ISEMPTY_DIM_OBJ 115 -#define ZEND_ISSET_ISEMPTY_VAR 115 -#define ZEND_ISSET_ISEMPTY_DIM_OBJ 116 +#define ZEND_IMPORT_FUNCTION 116 +#define ZEND_IMPORT_CLASS 117 +#define ZEND_IMPORT_CONST 118 /* end of block */ diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index a45781a2ba..b9d91e06c3 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -1402,6 +1402,67 @@ binary_assign_op_addr: { FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2)); } NEXT_OPCODE(); + case ZEND_IMPORT_FUNCTION: + { + zend_class_entry *ce; + zend_function *function; + + ce = EX(Ts)[EX(opline)->op1.u.var].EA.class_entry; + + if (EX(opline)->op2.op_type != IS_UNUSED) { + char *function_name_strval; + int function_name_strlen; + + function_name_strval = EX(opline)->op2.u.constant.value.str.val; + function_name_strlen = EX(opline)->op2.u.constant.value.str.len; + + if (zend_hash_find(&ce->function_table, function_name_strval, function_name_strlen + 1, (void **) &function)==FAILURE) { + zend_error(E_ERROR, "Import: function %s() not found", function_name_strval); + } + if (zend_hash_add(EG(function_table), function_name_strval, function_name_strlen + 1, function, sizeof(zend_function), NULL) == FAILURE) { + zend_error(E_ERROR, "Import: function %s() already exists in current scope", function_name_strval); + } + function_add_ref(function); + } else { + //zend_hash_apply(&ce->function_table, (apply_func_t) zend_import_function, (void *) 1 TSRMLS_CC); + } + NEXT_OPCODE(); + } + case ZEND_IMPORT_CLASS: + { + zend_class_entry *ce; + zend_class_entry *import_ce; + + ce = EX(Ts)[EX(opline)->op1.u.var].EA.class_entry; + + if (EX(opline)->op2.op_type != IS_UNUSED) { + char *class_name_strval; + int class_name_strlen; + + class_name_strval = EX(opline)->op2.u.constant.value.str.val; + class_name_strlen = EX(opline)->op2.u.constant.value.str.len; + + if (zend_hash_find(&ce->class_table, class_name_strval, class_name_strlen + 1, (void **) &import_ce)==FAILURE) { + zend_error(E_ERROR, "Import: class %s not found", class_name_strval); + } + if (zend_hash_add(EG(class_table), class_name_strval, class_name_strlen + 1, import_ce, sizeof(zend_class_entry), NULL) == FAILURE) { + zend_error(E_ERROR, "Import: class %s already exists in current scope", class_name_strval); + } + zend_class_add_ref(import_ce); + } else { + //zend_hash_apply(&ce->function_table, (apply_func_t) zend_import_function, (void *) 1 TSRMLS_CC); + } + + NEXT_OPCODE(); + } + case ZEND_IMPORT_CONST: + { + zend_class_entry *ce; + + ce = EX(Ts)[EX(opline)->op1.u.var].EA.class_entry; + + NEXT_OPCODE(); + } case ZEND_FETCH_CLASS: { if (EX(opline)->op1.op_type == IS_UNUSED) { diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h index 2139e54fcf..7b029b0e31 100644 --- a/Zend/zend_globals.h +++ b/Zend/zend_globals.h @@ -119,6 +119,8 @@ struct _zend_compiler_globals { int interactive; zend_bool increment_lineno; + + zend_llist import_commands; }; diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index accea627e6..0e36bc02a5 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -135,6 +135,7 @@ %token T_DOLLAR_OPEN_CURLY_BRACES %token T_CURLY_OPEN %token T_PAAMAYIM_NEKUDOTAYIM +%token T_IMPORT T_FROM %% /* Rules */ @@ -206,10 +207,31 @@ unticked_statement: | T_DECLARE { zend_do_declare_begin(TSRMLS_C); } '(' declare_list ')' declare_statement { zend_do_declare_end(TSRMLS_C); } | ';' /* empty statement */ | T_TRY { zend_do_try(&$1 TSRMLS_CC); } '{' inner_statement_list '}' - T_CATCH '(' catch_class_entry T_VARIABLE ')' { zend_do_begin_catch(&$1, &$8, &$9, 1 TSRMLS_CC); } '{' inner_statement_list '}' { zend_do_end_catch(&$1 TSRMLS_CC); } + T_CATCH '(' catch_or_import_class_entry T_VARIABLE ')' { zend_do_begin_catch(&$1, &$8, &$9, 1 TSRMLS_CC); } '{' inner_statement_list '}' { zend_do_end_catch(&$1 TSRMLS_CC); } additional_catches | T_THROW expr ';' { zend_do_throw(&$2 TSRMLS_CC); } | T_DELETE cvar ';' { zend_do_end_variable_parse(BP_VAR_UNSET, 0 TSRMLS_CC); zend_do_unset(&$1, ZEND_UNSET_OBJ TSRMLS_CC); } + | T_IMPORT { zend_do_begin_import(TSRMLS_C); } import_rule T_FROM catch_or_import_class_entry { zend_do_end_import(&$5 TSRMLS_CC); } ';' +; + + +import_rule: + '*' { zend_do_import(T_FUNCTION, NULL TSRMLS_CC); zend_do_import(T_CLASS, NULL TSRMLS_CC); zend_do_import(T_CONST, NULL TSRMLS_CC); } + | import_commands +; + +import_commands: + import_commands ',' import_command + | import_command +; + +import_command: + T_FUNCTION T_STRING { zend_do_import(T_FUNCTION, &$2 TSRMLS_CC); } + | T_CLASS T_STRING { zend_do_import(T_CLASS, &$2 TSRMLS_CC); } + | T_CONST T_STRING { zend_do_import(T_CONST, &$2 TSRMLS_CC); } + | T_FUNCTION '*' { zend_do_import(T_FUNCTION, NULL TSRMLS_CC); } + | T_CLASS '*' { zend_do_import(T_CLASS, NULL TSRMLS_CC); } + | T_CONST '*' { zend_do_import(T_CONST, NULL TSRMLS_CC); } ; additional_catches: @@ -218,8 +240,8 @@ additional_catches: ; non_empty_additional_catches: - non_empty_additional_catches T_CATCH '(' catch_class_entry T_VARIABLE ')' { zend_do_begin_catch(&$2, &$4, &$5, 0 TSRMLS_CC); } '{' inner_statement_list '}' { zend_do_end_catch(&$2 TSRMLS_CC); } - | T_CATCH '(' catch_class_entry T_VARIABLE ')' { zend_do_begin_catch(&$1, &$3, &$4, 0 TSRMLS_CC); } '{' inner_statement_list '}' { zend_do_end_catch(&$1 TSRMLS_CC); } + non_empty_additional_catches T_CATCH '(' catch_or_import_class_entry T_VARIABLE ')' { zend_do_begin_catch(&$2, &$4, &$5, 0 TSRMLS_CC); } '{' inner_statement_list '}' { zend_do_end_catch(&$2 TSRMLS_CC); } + | T_CATCH '(' catch_or_import_class_entry T_VARIABLE ')' { zend_do_begin_catch(&$1, &$3, &$4, 0 TSRMLS_CC); } '{' inner_statement_list '}' { zend_do_end_catch(&$1 TSRMLS_CC); } ; @@ -542,7 +564,7 @@ parse_class_name_entry: | T_STRING T_PAAMAYIM_NEKUDOTAYIM { $$ = $1; zend_str_tolower($$.u.constant.value.str.val, $$.u.constant.value.str.len); } ; -catch_class_entry: +catch_or_import_class_entry: parse_class_entry T_STRING { do_fetch_class(&$$, &$1, &$2 TSRMLS_CC); } | T_STRING { do_fetch_class(&$$, NULL, &$1 TSRMLS_CC); } ; diff --git a/Zend/zend_language_scanner.l b/Zend/zend_language_scanner.l index 16ad7d8c82..d3b2f03c4e 100644 --- a/Zend/zend_language_scanner.l +++ b/Zend/zend_language_scanner.l @@ -669,6 +669,14 @@ NEWLINE ("\r"|"\n"|"\r\n") return T_INCLUDE; } +<ST_IN_SCRIPTING>"import" { + return T_IMPORT; +} + +<ST_IN_SCRIPTING>"from" { + return T_FROM; +} + <ST_IN_SCRIPTING>"include_once" { return T_INCLUDE_ONCE; } |