This repository has been archived on 2020-06-07. You can view files and clone it, but cannot push or open issues or pull requests.
php-armadillo/src/operators.cc

228 lines
6.7 KiB
C++
Raw Normal View History

2019-04-16 11:00:26 +00:00
//
// php-armadillo/operators.cc
//
// @Author CismonX
//
#include "php_arma.hh"
2019-04-16 11:00:50 +00:00
#include "operators.hh"
2019-04-16 11:00:26 +00:00
#include "complex.hh"
#if PHP_VERSION_ID >= 70300
2019-04-18 10:15:33 +00:00
// See https://github.com/php/php-src/blob/PHP-7.3/UPGRADING.INTERNALS section 3.1.b.
2019-04-16 11:00:26 +00:00
#define EX_CONSTANT(op) RT_CONSTANT(EX(opline), op)
#endif
namespace php_arma
{
zend_always_inline
zval *get_zval_ptr_undef(
zend_uchar op_type,
2019-04-16 11:00:50 +00:00
const znode_op *op,
2019-04-16 11:00:26 +00:00
zend_free_op *free_op,
zend_execute_data *execute_data
) {
switch (op_type) {
case IS_TMP_VAR:
case IS_VAR:
2019-04-16 11:00:50 +00:00
return *free_op = EX_VAR(op->var);
2019-04-16 11:00:26 +00:00
case IS_CONST:
2019-04-16 11:00:50 +00:00
return EX_CONSTANT(*op);
2019-04-16 11:00:26 +00:00
case IS_CV:
2019-04-16 11:00:50 +00:00
return EX_VAR(op->var);
2019-04-16 11:00:26 +00:00
default:
return nullptr;
}
}
template <typename F>
zend_always_inline
int op_handler(zend_execute_data *execute_data, F handler)
{
const zend_op *opline = EX(opline);
zend_free_op free_op1 = nullptr;
zend_free_op free_op2 = nullptr;
2019-04-19 12:08:43 +00:00
auto op1 = get_zval_ptr_undef(opline->op1_type, &opline->op1, &free_op1, execute_data);
auto op2 = get_zval_ptr_undef(opline->op2_type, &opline->op2, &free_op2, execute_data);
zend_class_entry *ce = nullptr;
2019-04-16 11:00:26 +00:00
2019-04-19 12:08:43 +00:00
if (EXPECTED(op1)) {
2019-04-16 11:00:50 +00:00
ZVAL_DEREF(op1);
2019-04-19 12:08:43 +00:00
if (Z_TYPE_P(op1) == IS_OBJECT) {
ce = Z_OBJCE_P(op1);
}
2019-04-16 11:00:50 +00:00
}
if (op2) {
ZVAL_DEREF(op2);
2019-04-19 12:08:43 +00:00
if (ce == nullptr) {
if (Z_TYPE_P(op2) == IS_OBJECT) {
ce = Z_OBJCE_P(op2);
} else {
return ZEND_USER_OPCODE_DISPATCH;
}
}
2019-04-16 11:00:26 +00:00
}
2019-04-19 12:08:43 +00:00
zval *result = opline->result_type == IS_UNUSED ? nullptr : EX_VAR(opline->result.var);
if (ce == nullptr || !handler(op1, op2, result, ce)) {
2019-04-16 11:00:26 +00:00
return ZEND_USER_OPCODE_DISPATCH;
}
if (free_op2) {
zval_ptr_dtor_nogc(free_op2);
}
if (free_op1) {
zval_ptr_dtor_nogc(free_op1);
}
EX(opline) = opline + 1;
return ZEND_USER_OPCODE_CONTINUE;
}
int add_handler(zend_execute_data *execute_data)
{
2019-04-18 10:15:33 +00:00
return op_handler(execute_data, [] (auto zv1, auto zv2, auto rv, auto ce) {
PHP_ARMA_OPERATOR_BEGIN(complex_ce)
2019-04-16 11:00:26 +00:00
PHP_ARMA_COMPLEX_OPERATOR(double, add)
PHP_ARMA_OPERATOR_END();
return false;
});
}
int add_assign_handler(zend_execute_data *execute_data)
{
2019-04-19 12:08:43 +00:00
return op_handler(execute_data, [] (auto zv1, auto zv2, auto rv, auto ce) {
2019-04-18 10:15:33 +00:00
PHP_ARMA_OPERATOR_BEGIN(complex_ce)
2019-04-16 11:00:26 +00:00
PHP_ARMA_COMPLEX_OPERATOR_ASSIGN(double, add)
PHP_ARMA_OPERATOR_END();
return false;
});
}
int sub_handler(zend_execute_data *execute_data)
{
2019-04-18 10:15:33 +00:00
return op_handler(execute_data, [] (auto zv1, auto zv2, auto rv, auto ce) {
PHP_ARMA_OPERATOR_BEGIN(complex_ce)
2019-04-16 11:00:26 +00:00
PHP_ARMA_COMPLEX_OPERATOR(double, sub)
PHP_ARMA_OPERATOR_END();
return false;
});
}
int sub_assign_handler(zend_execute_data *execute_data)
{
2019-04-19 12:08:43 +00:00
return op_handler(execute_data, [] (auto zv1, auto zv2, auto rv, auto ce) {
2019-04-18 10:15:33 +00:00
PHP_ARMA_OPERATOR_BEGIN(complex_ce)
2019-04-16 11:00:26 +00:00
PHP_ARMA_COMPLEX_OPERATOR_ASSIGN(double, sub)
PHP_ARMA_OPERATOR_END();
return false;
});
}
int mul_handler(zend_execute_data *execute_data)
{
2019-04-18 10:15:33 +00:00
return op_handler(execute_data, [] (auto zv1, auto zv2, auto rv, auto ce) {
PHP_ARMA_OPERATOR_BEGIN(complex_ce)
2019-04-16 11:00:26 +00:00
PHP_ARMA_COMPLEX_OPERATOR(double, mul)
PHP_ARMA_OPERATOR_END();
return false;
});
}
int mul_assign_handler(zend_execute_data *execute_data)
{
2019-04-19 12:08:43 +00:00
return op_handler(execute_data, [] (auto zv1, auto zv2, auto rv, auto ce) {
2019-04-18 10:15:33 +00:00
PHP_ARMA_OPERATOR_BEGIN(complex_ce)
2019-04-16 11:00:26 +00:00
PHP_ARMA_COMPLEX_OPERATOR_ASSIGN(double, mul)
PHP_ARMA_OPERATOR_END();
return false;
});
}
int div_handler(zend_execute_data *execute_data)
{
2019-04-18 10:15:33 +00:00
return op_handler(execute_data, [] (auto zv1, auto zv2, auto rv, auto ce) {
PHP_ARMA_OPERATOR_BEGIN(complex_ce)
2019-04-16 11:00:26 +00:00
PHP_ARMA_COMPLEX_OPERATOR(double, div)
PHP_ARMA_OPERATOR_END();
return false;
});
}
int div_assign_handler(zend_execute_data *execute_data)
{
2019-04-19 12:08:43 +00:00
return op_handler(execute_data, [] (auto zv1, auto zv2, auto rv, auto ce) {
2019-04-18 10:15:33 +00:00
PHP_ARMA_OPERATOR_BEGIN(complex_ce)
2019-04-16 11:00:26 +00:00
PHP_ARMA_COMPLEX_OPERATOR_ASSIGN(double, div)
PHP_ARMA_OPERATOR_END();
return false;
});
}
int pow_handler(zend_execute_data *execute_data)
{
2019-04-18 10:15:33 +00:00
return op_handler(execute_data, [] (auto zv1, auto zv2, auto rv, auto ce) {
PHP_ARMA_OPERATOR_BEGIN(complex_ce)
2019-04-16 11:00:26 +00:00
PHP_ARMA_COMPLEX_OPERATOR(double, pow)
PHP_ARMA_OPERATOR_END();
return false;
});
}
2019-04-16 11:00:50 +00:00
int pow_assign_handler(zend_execute_data *execute_data)
{
2019-04-19 12:08:43 +00:00
return op_handler(execute_data, [] (auto zv1, auto zv2, auto rv, auto ce) {
2019-04-18 10:15:33 +00:00
PHP_ARMA_OPERATOR_BEGIN(complex_ce)
2019-04-16 11:00:50 +00:00
PHP_ARMA_COMPLEX_OPERATOR_ASSIGN(double, pow)
PHP_ARMA_OPERATOR_END();
return false;
});
}
2019-04-16 11:00:26 +00:00
int bw_not_handler(zend_execute_data *execute_data)
{
2019-04-18 10:15:33 +00:00
return op_handler(execute_data, [] (auto zv1, auto zv2, auto rv, auto ce) {
PHP_ARMA_OPERATOR_BEGIN(complex_ce)
2019-04-16 11:00:26 +00:00
PHP_ARMA_COMPLEX_OPERATOR(double, conj)
PHP_ARMA_OPERATOR_END();
return false;
});
}
2019-04-16 13:23:47 +00:00
template <typename... Ts>
zend_always_inline
void set_op_handlers(Ts... op_handlers)
{
for (auto [opcode, handler] : { op_handlers... }) {
zend_set_user_opcode_handler(opcode, handler);
}
}
2019-04-16 11:00:50 +00:00
void operators_init()
2019-04-16 11:00:26 +00:00
{
2019-04-16 13:23:47 +00:00
set_op_handlers(
std::tuple(ZEND_ADD, add_handler),
std::tuple(ZEND_ASSIGN_ADD, add_assign_handler),
std::tuple(ZEND_SUB, sub_handler),
std::tuple(ZEND_ASSIGN_SUB, sub_assign_handler),
std::tuple(ZEND_MUL, mul_handler),
std::tuple(ZEND_ASSIGN_MUL, mul_assign_handler),
std::tuple(ZEND_DIV, div_handler),
std::tuple(ZEND_ASSIGN_DIV, div_assign_handler),
std::tuple(ZEND_POW, pow_handler),
std::tuple(ZEND_ASSIGN_POW, pow_assign_handler),
std::tuple(ZEND_BW_NOT, bw_not_handler)
);
2019-04-16 11:00:26 +00:00
}
}