]> granicus.if.org Git - php/commitdiff
allow expressions within constants, so the following is possible
authorSterling Hughes <sterling@php.net>
Thu, 10 Apr 2003 15:43:47 +0000 (15:43 +0000)
committerSterling Hughes <sterling@php.net>
Thu, 10 Apr 2003 15:43:47 +0000 (15:43 +0000)
class foo {
const a = 1<<0;
const b = 1<<1;
const c = a | b;
}

this makes const a compile-time expression.  all other operators are
unaffected.

Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_language_parser.y

index ec2d09bad7ad68dfdfa789f0e9a4a859007c4f10..b05af5b53d7bad4bd6aba09a6e537f942769c684 100644 (file)
@@ -166,6 +166,43 @@ static zend_uint get_temporary_variable(zend_op_array *op_array)
 }
 
 
+void zend_do_fold_binary_op(zend_uchar op, znode *result, znode *op1, znode *op2 TSRMLS_DC)
+{
+       int (*do_op)(zval *, zval *, zval *);
+       zend_op *opline;
+
+       if (op == ZEND_SL) {
+               do_op = shift_left_function;
+       } else if (op == ZEND_SR) {
+               do_op = shift_right_function;
+       } else if (op == ZEND_BW_OR) {
+               do_op = bitwise_or_function;
+       } else if (op == ZEND_BW_AND) {
+               do_op = bitwise_and_function;
+       } else if (op == ZEND_BW_XOR) {
+               do_op = bitwise_xor_function;
+       } else if (op == ZEND_CONCAT) {
+               do_op = concat_function;
+       } else if (op == ZEND_ADD) {
+               do_op = add_function;
+       } else if (op == ZEND_SUB) {
+               do_op = sub_function;
+       } else if (op == ZEND_MUL) {
+               do_op = mul_function;
+       } else if (op == ZEND_DIV) {
+               do_op = div_function;
+       } else if (op == ZEND_MOD) {
+               do_op = mod_function;
+       } else if (op == ZEND_BW_NOT) {
+               bitwise_not_function(&result->u.constant, &op1->u.constant);
+               return;
+       } else if (op == ZEND_BOOL_XOR) {
+               do_op = boolean_xor_function;
+       }
+
+       do_op(&result->u.constant, &op1->u.constant, &op2->u.constant);
+}
+
 void zend_do_binary_op(zend_uchar op, znode *result, znode *op1, znode *op2 TSRMLS_DC)
 {
        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
@@ -2518,6 +2555,23 @@ void zend_do_end_new_object(znode *result, znode *new_token, znode *argument_lis
        *result = CG(active_op_array)->opcodes[new_token->u.opline_num].op1;
 }
 
+void zend_do_fold_constant(znode *result, znode *constant_name TSRMLS_DC)
+{
+       zval **zresult;
+       
+       if (zend_hash_find(&CG(active_class_entry)->constants_table, constant_name->u.constant.value.str.val,
+                          constant_name->u.constant.value.str.len+1, (void **) &zresult) != SUCCESS) {
+               if (zend_get_constant(constant_name->u.constant.value.str.val, constant_name->u.constant.value.str.len, &result->u.constant)) {
+                       return;
+               } else {
+                       zend_error(E_COMPILE_ERROR, "Cannot find %s constant in class %s\n", 
+                                  constant_name->u.constant.value.str.val, CG(active_class_entry)->name);
+               }
+       }
+
+       result->u.constant = **zresult;
+       zval_copy_ctor(&result->u.constant);
+}
 
 void zend_do_fetch_constant(znode *result, znode *constant_container, znode *constant_name, int mode TSRMLS_DC)
 {
index 1d735d3c06fd472d893ab58ce1b3d7a7462e2cf9..f1cfe53515d81406a243bd8028ab12c6c4c1c719 100644 (file)
@@ -274,6 +274,7 @@ int zend_get_zendleng(TSRMLS_D);
 
 
 /* parser-driven code generators */
+void zend_do_fold_binary_op(zend_uchar op, znode *result, znode *op1, znode *op2 TSRMLS_DC);
 void zend_do_binary_op(zend_uchar op, znode *result, znode *op1, znode *op2 TSRMLS_DC);
 void zend_do_unary_op(zend_uchar op, znode *result, znode *op1 TSRMLS_DC);
 void zend_do_binary_assign_op(zend_uchar op, znode *result, znode *op1, znode *op2 TSRMLS_DC);
index bdc00084880f500a8502cc55d735d6aeab142322..1b2d116cbbb748fe15e13b119cec8926a20230ed 100644 (file)
@@ -332,8 +332,8 @@ namespace_var_declaration:
 ;
 
 namespace_const_declaration:
-               namespace_const_declaration ',' T_STRING '=' static_scalar      { zend_do_declare_namespace_constant(&$3, &$5 TSRMLS_CC); }
-       |       T_CONST T_STRING '=' static_scalar      { zend_do_declare_namespace_constant(&$2, &$4 TSRMLS_CC); }
+               namespace_const_declaration ',' T_STRING '=' const_scalar_expr  { zend_do_declare_namespace_constant(&$3, &$5 TSRMLS_CC); }
+       |       T_CONST T_STRING '=' const_scalar_expr  { zend_do_declare_namespace_constant(&$2, &$4 TSRMLS_CC); }
 ;
 
 extends_from:
@@ -545,8 +545,8 @@ class_variable_declaration:
 ;
 
 class_constant_declaration:
-               class_constant_declaration ',' T_STRING '=' static_scalar       { zend_do_declare_class_constant(&$3, &$5 TSRMLS_CC); }
-       |       T_CONST T_STRING '=' static_scalar      { zend_do_declare_class_constant(&$2, &$4 TSRMLS_CC); }
+               class_constant_declaration ',' T_STRING '=' const_scalar_expr   { zend_do_declare_class_constant(&$3, &$5 TSRMLS_CC); }
+       |       T_CONST T_STRING '=' const_scalar_expr  { zend_do_declare_class_constant(&$2, &$4 TSRMLS_CC); }
 ;
 
 echo_expr_list:        
@@ -700,16 +700,46 @@ common_scalar:
 ;
 
 
+const_scalar_expr: /* compile-time evaluated scalar expressions */
+               const_scalar { $$ = $1; }
+       |   const_scalar_expr_list { $$ = $1; }
+;
+
+const_scalar_expr_list:
+               const_scalar_expr T_SL const_scalar_expr { zend_do_fold_binary_op(ZEND_SL, &$$, &$1, &$3 TSRMLS_CC); }
+       |       const_scalar_expr T_SR const_scalar_expr { zend_do_fold_binary_op(ZEND_SR, &$$, &$1, &$3 TSRMLS_CC); }
+       |       const_scalar_expr T_LOGICAL_XOR  const_scalar_expr { zend_do_fold_binary_op(ZEND_BOOL_XOR, &$$, &$1, &$3 TSRMLS_CC); }
+       |   const_scalar_expr '|'  const_scalar_expr { zend_do_fold_binary_op(ZEND_BW_OR, &$$, &$1, &$3 TSRMLS_CC); } 
+       |   const_scalar_expr '&'  const_scalar_expr { zend_do_fold_binary_op(ZEND_BW_AND, &$$, &$1, &$3 TSRMLS_CC); } 
+       |   const_scalar_expr '^'  const_scalar_expr { zend_do_fold_binary_op(ZEND_BW_XOR, &$$, &$1, &$3 TSRMLS_CC); } 
+       |       const_scalar_expr '.'  const_scalar_expr { zend_do_fold_binary_op(ZEND_CONCAT, &$$, &$1, &$3 TSRMLS_CC); } 
+       |   const_scalar_expr '+'  const_scalar_expr { zend_do_fold_binary_op(ZEND_ADD, &$$, &$1, &$3 TSRMLS_CC); } 
+       |   const_scalar_expr '-'  const_scalar_expr { zend_do_fold_binary_op(ZEND_SUB, &$$, &$1, &$3 TSRMLS_CC); }
+       |   const_scalar_expr '*'  const_scalar_expr { zend_do_fold_binary_op(ZEND_MUL, &$$, &$1, &$3 TSRMLS_CC); } 
+       |   const_scalar_expr '/'  const_scalar_expr { zend_do_fold_binary_op(ZEND_DIV, &$$, &$1, &$3 TSRMLS_CC); } 
+       |   const_scalar_expr '%'  const_scalar_expr { zend_do_fold_binary_op(ZEND_MOD, &$$, &$1, &$3 TSRMLS_CC); } 
+       |   const_scalar_expr '~'  const_scalar_expr { zend_do_fold_binary_op(ZEND_BW_NOT, &$$, &$1, &$3 TSRMLS_CC); }
+       |   '(' const_scalar_expr ')' { $$ = $2; }
+;
+
+const_scalar:
+               common_scalar { $$ = $1; }
+       |       T_STRING { zend_do_fold_constant(&$$, &$1 TSRMLS_CC); }
+       |       '+' const_scalar { $$ = $2; }
+       |       '-' const_scalar { zval minus_one; minus_one.type = IS_LONG; minus_one.value.lval = -1; mul_function(&$2.u.constant, &$2.u.constant, &minus_one TSRMLS_CC); $$ = $2; }
+       |       T_ARRAY '(' static_array_pair_list ')' { $$ = $3; $$.u.constant.type = IS_CONSTANT_ARRAY; }
+       |       class_or_namespace_constant { /* FIXME */ }
+;
+
 static_scalar: /* compile-time evaluated scalars */
                common_scalar           { $$ = $1; }
        |       T_STRING                { zend_do_fetch_constant(&$$, NULL, &$1, ZEND_CT TSRMLS_CC); }
        |       '+' static_scalar       { $$ = $2; }
-       |       '-' static_scalar       { zval minus_one;  minus_one.type = IS_LONG; minus_one.value.lval = -1;  mul_function(&$2.u.constant, &$2.u.constant, &minus_one TSRMLS_CC);  $$ = $2; }
+       |       '-' static_scalar       { zval minus_one;  minus_one.type = IS_LONG; minus_one.value.lval = -1;  mul_function(&$2.u.constant, &$2.u.constant, &minus_one TSRMLS_CC);  $$ = $2; } 
        |       T_ARRAY '(' static_array_pair_list ')' { $$ = $3; $$.u.constant.type = IS_CONSTANT_ARRAY; }
        |   class_or_namespace_constant { /* FIXME */ }
 ;
 
-
 scalar:
                T_STRING                                { zend_do_fetch_constant(&$$, NULL, &$1, ZEND_RT TSRMLS_CC); }
        |       T_STRING_VARNAME                { $$ = $1; }