}
+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);
*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)
{
;
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:
;
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:
;
+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; }