return opline;
}
+static void zend_emit_tick(TSRMLS_D) {
+ zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+
+ opline->opcode = ZEND_TICKS;
+ SET_UNUSED(opline->op1);
+ SET_UNUSED(opline->op2);
+ opline->extended_value = Z_LVAL(CG(declarables).ticks);
+}
+
static zend_bool zend_is_variable(zend_ast *ast) {
return ast->kind == ZEND_AST_VAR || ast->kind == ZEND_AST_DIM
|| ast->kind == ZEND_AST_PROP || ast->kind == ZEND_AST_STATIC_PROP
|| ast->kind == ZEND_AST_STATIC_CALL;
}
+static zend_bool zend_is_unticked_stmt(zend_ast *ast) {
+ return ast->kind == ZEND_AST_STMT_LIST || ast->kind == ZEND_AST_LABEL;
+}
+
static zend_bool zend_can_write_to_variable(zend_ast *ast) {
while (ast->kind == ZEND_AST_DIM || ast->kind == ZEND_AST_PROP) {
ast = ast->child[0];
switch (ast->kind) {
case ZEND_AST_STMT_LIST:
zend_compile_stmt_list(ast TSRMLS_CC);
- return;
+ break;
case ZEND_AST_GLOBAL:
zend_compile_global_var(ast TSRMLS_CC);
- return;
+ break;
case ZEND_AST_UNSET:
zend_compile_unset(ast TSRMLS_CC);
- return;
+ break;
case ZEND_AST_RETURN:
zend_compile_return(ast TSRMLS_CC);
- return;
+ break;
case ZEND_ECHO:
zend_compile_echo(ast TSRMLS_CC);
- return;
+ break;
case ZEND_THROW:
zend_compile_throw(ast TSRMLS_CC);
- return;
+ break;
case ZEND_BRK:
case ZEND_CONT:
zend_compile_break_continue(ast TSRMLS_CC);
- return;
+ break;
case ZEND_GOTO:
zend_compile_goto(ast TSRMLS_CC);
- return;
+ break;
case ZEND_AST_LABEL:
zend_compile_label(ast TSRMLS_CC);
- return;
+ break;
EMPTY_SWITCH_DEFAULT_CASE()
}
+
+ if (Z_LVAL(CG(declarables).ticks) && !zend_is_unticked_stmt(ast)) {
+ zend_emit_tick(TSRMLS_C);
+ }
}
void zend_compile_expr(znode *result, zend_ast *ast TSRMLS_DC) {
;
top_statement:
- statement { zend_verify_namespace(TSRMLS_C); }
+ statement { AS($1); zend_verify_namespace(TSRMLS_C); }
| function_declaration_statement { zend_verify_namespace(TSRMLS_C); zend_do_early_binding(TSRMLS_C); }
| class_declaration_statement { zend_verify_namespace(TSRMLS_C); zend_do_early_binding(TSRMLS_C); }
| T_HALT_COMPILER '(' ')' ';' { zend_do_halt_compiler_register(TSRMLS_C); YYACCEPT; }
inner_statement:
- statement
+ statement { AS($1); }
| function_declaration_statement
| class_declaration_statement
| T_HALT_COMPILER '(' ')' ';' { zend_error_noreturn(E_COMPILE_ERROR, "__HALT_COMPILER() can only be used from the outermost scope"); }
statement:
- unticked_statement { AS($$); DO_TICKS(); }
- | T_STRING ':' { $$.u.ast = zend_ast_create_unary(ZEND_AST_LABEL, AST_ZVAL(&$1)); AS($$); }
+ unticked_statement { $$.u.ast = $1.u.ast; }
+ | T_STRING ':' { $$.u.ast = zend_ast_create_unary(ZEND_AST_LABEL, AST_ZVAL(&$1)); }
;
unticked_statement:
'{' inner_statement_list '}' { AN($$); }
- | T_IF parenthesis_expr { AC($2); zend_do_if_cond(&$2, &$1 TSRMLS_CC); } statement { zend_do_if_after_statement(&$1, 1 TSRMLS_CC); } elseif_list else_single { zend_do_if_end(TSRMLS_C); AN($$); }
+ | T_IF parenthesis_expr { AC($2); zend_do_if_cond(&$2, &$1 TSRMLS_CC); } statement { AS($4); zend_do_if_after_statement(&$1, 1 TSRMLS_CC); } elseif_list else_single { zend_do_if_end(TSRMLS_C); AN($$); }
| T_IF parenthesis_expr ':' { AC($2); zend_do_if_cond(&$2, &$1 TSRMLS_CC); } inner_statement_list { zend_do_if_after_statement(&$1, 1 TSRMLS_CC); } new_elseif_list new_else_single T_ENDIF ';' { zend_do_if_end(TSRMLS_C); AN($$); }
| T_WHILE { $1.u.op.opline_num = get_next_op_number(CG(active_op_array)); } parenthesis_expr { AC($3); zend_do_while_cond(&$3, &$$ TSRMLS_CC); } while_statement { zend_do_while_end(&$1, &$4 TSRMLS_CC); AN($$); }
- | T_DO { $1.u.op.opline_num = get_next_op_number(CG(active_op_array)); zend_do_do_while_begin(TSRMLS_C); } statement T_WHILE { $4.u.op.opline_num = get_next_op_number(CG(active_op_array)); } parenthesis_expr ';' { AC($6); zend_do_do_while_end(&$1, &$4, &$6 TSRMLS_CC); AN($$); }
+ | T_DO { $1.u.op.opline_num = get_next_op_number(CG(active_op_array)); zend_do_do_while_begin(TSRMLS_C); } statement T_WHILE { AS($3); $4.u.op.opline_num = get_next_op_number(CG(active_op_array)); } parenthesis_expr ';' { AC($6); zend_do_do_while_end(&$1, &$4, &$6 TSRMLS_CC); AN($$); }
| T_FOR
'('
for_expr
;
for_statement:
- statement
+ statement { AS($1); }
| ':' inner_statement_list T_ENDFOR ';'
;
foreach_statement:
- statement
+ statement { AS($1); }
| ':' inner_statement_list T_ENDFOREACH ';'
;
declare_statement:
- statement
+ statement { AS($1); }
| ':' inner_statement_list T_ENDDECLARE ';'
;
while_statement:
- statement
+ statement { AS($1); }
| ':' inner_statement_list T_ENDWHILE ';'
;
elseif_list:
/* empty */
- | elseif_list T_ELSEIF parenthesis_expr { AC($3); zend_do_if_cond(&$3, &$2 TSRMLS_CC); } statement { zend_do_if_after_statement(&$2, 0 TSRMLS_CC); }
+ | elseif_list T_ELSEIF parenthesis_expr { AC($3); zend_do_if_cond(&$3, &$2 TSRMLS_CC); } statement { AS($5); zend_do_if_after_statement(&$2, 0 TSRMLS_CC); }
;
else_single:
/* empty */
- | T_ELSE statement
+ | T_ELSE statement { AS($2); }
;