[INTERPRETER]

* NEW: Put every '_operators' interface related methods in the same source 
  file.

[GB.GSL]
* NEW: Polynomial _call() special method now is a synonymous of its Eval() 
  method. That way, you can write 'P(X)' to get the value of P(X).


git-svn-id: svn://localhost/gambas/trunk@4933 867c0c6c-44f3-4631-809d-bfa615b0a4ec
This commit is contained in:
Benoît Minisini 2012-07-10 14:35:17 +00:00
parent 7d03122fa0
commit 55e313b8f5
6 changed files with 327 additions and 358 deletions

View file

@ -751,90 +751,6 @@ BEGIN_METHOD(Polynomial_Solve, GB_BOOLEAN want_croot)
END_METHOD
#if 0
BEGIN_METHOD_VOID(Polynomial_SolveComplex)
double *data = DATA(THIS);
int nr, i, dg, ret;
GB_ARRAY result;
double r[3];
double *z = NULL;
gsl_poly_complex_workspace *work;
CCOMPLEX **root = NULL;
dg = get_degree(THIS) + 1;
switch(dg)
{
case 1:
GB.ReturnNull();
return;
case 2:
r[0] = -data[0] / data[1];
nr = 1;
break;
case 3:
nr = gsl_poly_solve_quadratic(data[2], data[1], data[0], &r[0], &r[1]);
break;
case 4:
if (data[3] == 1.0)
{
nr = gsl_poly_solve_cubic(data[2], data[1], data[0], &r[0], &r[1], &r[2]);
break;
}
default:
work = gsl_poly_complex_workspace_alloc(dg);
GB.Alloc(POINTER(&z), sizeof(double) * (dg - 1) * 2);
ret = gsl_poly_complex_solve(data, dg, work, z);
gsl_poly_complex_workspace_free(work);
if (ret != GSL_SUCCESS)
{
GB.Free(POINTER(&z));
return;
}
nr = dg - 1;
}
GB.Array.New(&result, CLASS_Complex, nr);
if (nr > 0)
root = (CCOMPLEX **)GB.Array.Get(result, 0);
if (!z)
{
for (i = 0; i < nr; i++)
{
root[i] = COMPLEX_create(gsl_complex_rect(r[i], 0));
GB.Ref(root[i]);
}
}
else
{
if (nr > 0)
{
for (i = 0; i < nr; i++)
{
root[i] = COMPLEX_create(gsl_complex_rect(z[i * 2], z[i * 2 + 1]));
GB.Ref(root[i]);
}
}
GB.Free(POINTER(&z));
}
GB.ReturnObject(result);
END_METHOD
#endif
//---------------------------------------------------------------------------
GB_DESC PolynomialDesc[] =
@ -852,6 +768,7 @@ GB_DESC PolynomialDesc[] =
GB_METHOD("_get", "v", Polynomial_get, "(Index)i"),
GB_METHOD("_put", NULL, Polynomial_put, "(Value)v(Index)i"),
GB_METHOD("_call", "v", Polynomial_Eval, "(X)v"),
GB_METHOD("Eval", "v", Polynomial_Eval, "(X)v"),
GB_METHOD("Solve", "Array", Polynomial_Solve, "[(Complex)b]"),

View file

@ -31,7 +31,7 @@ gbx3_SOURCES = \
gb_table.c \
gb_list.c \
gbx_type.h gbx_type.c \
gbx_exec.h gbx_exec.c gbx_exec_push.c gbx_exec_enum.c gbx_exec_pop.c \
gbx_exec.h gbx_exec.c gbx_exec_push.c gbx_exec_enum.c gbx_exec_pop.c gbx_exec_operator.c \
gbx_class_desc.h gbx_class.h gbx_class_init.c gbx_class.c gbx_class_native.c \
gbx_class_load.c gbx_class_load.h \
gbx_event.h gbx_event.c \

View file

@ -72,6 +72,16 @@ typedef
}
EXEC_HOOK;
enum {
OP_NOTHING = 0,
OP_OBJECT_FLOAT,
OP_FLOAT_OBJECT,
OP_OBJECT_CONV,
OP_CONV_OBJECT,
OP_OBJECT_OBJECT
};
#ifndef __GBX_EXEC_C
EXTERN STACK_CONTEXT EXEC_current;
@ -293,4 +303,12 @@ do { \
#define EXEC_set_native_error(_err) (ERROR_current->info.native = (_err))
#define EXEC_has_native_error() (ERROR_current->info.native)
bool EXEC_check_operator_single(VALUE *P1);
int EXEC_check_operator(VALUE *P1, VALUE *P2);
void EXEC_operator(uchar what, uchar op, VALUE *P1, VALUE *P2);
void EXEC_operator_object_add_quick(VALUE *P1, double val);
bool EXEC_comparator(uchar what, uchar op, VALUE *P1, VALUE *P2);
void EXEC_operator_object_abs(VALUE *P1);
void EXEC_operator_object_single(uchar op, VALUE *P1);
#endif /* */

View file

@ -182,153 +182,6 @@ static void *SubrTable[] =
SUBR_ptr, /* 95 9F */
};
//---- Object arithmetic helpers --------------------------------------------
#define OP_NONE 0
#define OP_OBJECT_FLOAT 1
#define OP_FLOAT_OBJECT 2
#define OP_OBJECT_CONV 3
#define OP_CONV_OBJECT 4
#define OP_OBJECT 5
static int check_operators(VALUE *P1, VALUE *P2)
{
if (TYPE_is_number(P1->type) && TYPE_is_object(P2->type))
{
if (P2->_object.object && OBJECT_class(P2->_object.object)->has_operators)
{
//*dynamic = P2->type == T_OBJECT;
return OP_FLOAT_OBJECT;
}
}
else if (TYPE_is_number(P2->type) && TYPE_is_object(P1->type))
{
if (P1->_object.object && OBJECT_class(P1->_object.object)->has_operators)
{
//*dynamic = P1->type == T_OBJECT;
return OP_OBJECT_FLOAT;
}
}
else if (TYPE_is_object(P1->type) && TYPE_is_object(P2->type) && P1->_object.object && P2->_object.object)
{
CLASS *class1 = OBJECT_class(P1->_object.object);
CLASS *class2 = OBJECT_class(P2->_object.object);
//*dynamic = P1->type == T_OBJECT || P2->type = T_OBJECT;
if (class1 && class1->has_operators)
{
if (class1 == class2)
return OP_OBJECT;
if (class2 && class2->has_operators)
return OP_OBJECT_CONV;
}
}
return OP_NONE;
}
static void operator_object_float(VALUE *P1, VALUE *P2, uchar op)
{
if (P1->_object.object)
{
void *(*func)(void *, double) = (void *(*)(void *, double))((void **)(OBJECT_class(P1->_object.object)->operators))[op];
VALUE_conv_float(P2);
void *result = (*func)(P1->_object.object, P2->_float.value);
OBJECT_REF(result, "operator_object_float");
OBJECT_UNREF(P1->_object.object, "operator_object_float");
P1->_object.object = result;
}
else
THROW(E_NULL);
}
static void operator_float_object(VALUE *P1, VALUE *P2, uchar op)
{
if (P2->_object.object)
{
void *(*func)(void *, double) = (void *(*)(void *, double))((void **)(OBJECT_class(P2->_object.object)->operators))[op];
VALUE_conv_float(P1);
void *result = (*func)(P2->_object.object, P1->_float.value);
OBJECT_REF(result, "operator_float_object");
P1->_object.class = P2->_object.class;
OBJECT_UNREF(P2->_object.object, "operator_float_object");
P1->_object.object = result;
}
else
THROW(E_NULL);
}
static void operator_object(VALUE *P1, VALUE *P2, uchar op)
{
if (P1->_object.object && P2->_object.object)
{
void *(*func)(void *, void *) = (void *(*)(void *, void *))((void **)(OBJECT_class(P1->_object.object)->operators))[op];
void *result = (*func)(P1->_object.object, P2->_object.object);
OBJECT_REF(result, "operator_object");
OBJECT_UNREF(P1->_object.object, "operator_object");
OBJECT_UNREF(P2->_object.object, "operator_object");
P1->_object.object = result;
}
else
THROW(E_NULL);
}
static void operator_object_conv(VALUE *P1, VALUE *P2, char op)
{
VALUE_conv(P2, (TYPE)P1->_object.class);
operator_object(P1, P2, op);
}
static void operator_conv_object(VALUE *P1, VALUE *P2, char op)
{
VALUE_conv(P1, (TYPE)P2->_object.class);
operator_object(P1, P2, op);
}
static int comparator_object_float(VALUE *P1, VALUE *P2, uchar op)
{
int (*func)(void *, double) = (int (*)(void *, double))((void **)(OBJECT_class(P1->_object.object)->operators))[op];
VALUE_conv_float(P2);
int result = (*func)(P1->_object.object, P2->_float.value);
OBJECT_UNREF(P1->_object.object, "comparator_object_float");
return result;
}
static int comparator_float_object(VALUE *P1, VALUE *P2, uchar op)
{
int (*func)(void *, double) = (int (*)(void *, double))((void **)(OBJECT_class(P2->_object.object)->operators))[op];
VALUE_conv_float(P1);
int result = (*func)(P2->_object.object, P1->_float.value);
OBJECT_UNREF(P2->_object.object, "comparator_float_object");
return result;
}
static int comparator_object(VALUE *P1, VALUE *P2, uchar op)
{
int (*func)(void *, void *) = (int (*)(void *, void *))((void **)(OBJECT_class(P1->_object.object)->operators))[op];
int result = (*func)(P1->_object.object, P2->_object.object);
OBJECT_UNREF(P1->_object.object, "comparator_object");
OBJECT_UNREF(P2->_object.object, "comparator_object");
return result;
}
static int comparator_object_conv(VALUE *P1, VALUE *P2, char op)
{
VALUE_conv(P2, (TYPE)P1->_object.class);
return comparator_object(P1, P2, op);
}
static int comparator_conv_object(VALUE *P1, VALUE *P2, char op)
{
VALUE_conv(P1, (TYPE)P2->_object.class);
return comparator_object(P1, P2, op);
}
//---- Main interpreter loop ------------------------------------------------
void EXEC_loop(void)
@ -1839,7 +1692,7 @@ _ADD_QUICK:
{
static void *_aq_jump[] = {
&&__AQ_VOID, &&__AQ_BOOLEAN, &&__AQ_BYTE, &&__AQ_SHORT, &&__AQ_INTEGER, &&__AQ_LONG, &&__AQ_SINGLE, &&__AQ_FLOAT,
&&__AQ_DATE, &&__AQ_STRING, &&__AQ_STRING, &&__AQ_POINTER
&&__AQ_DATE, &&__AQ_STRING, &&__AQ_STRING, &&__AQ_POINTER, &&__AQ_VARIANT, &&__AQ_BOOLEAN, &&__AQ_BOOLEAN, &&__AQ_BOOLEAN
};
TYPE NO_WARNING(type);
@ -1849,24 +1702,17 @@ _ADD_QUICK:
P1 = SP - 1;
if (UNLIKELY(TYPE_is_variant(P1->type)))
{
jump_end = &&__AQ_VARIANT_END;
VARIANT_undo(P1);
}
else
jump_end = &&__AQ_END;
jump_end = &&__AQ_END;
type = P1->type;
value = GET_XXX();
if (LIKELY(type <= T_POINTER))
__AQ_JUMP:
if (TYPE_is_object(type))
goto __AQ_OBJECT;
else
goto *_aq_jump[type];
__AQ_BOOLEAN:
THROW(E_TYPE, "Number", TYPE_get_name(type));
__AQ_VOID:
THROW(E_NRETURN);
@ -1910,6 +1756,25 @@ _ADD_QUICK:
P1->_pointer.value += value;
goto *jump_end;
__AQ_VARIANT:
jump_end = &&__AQ_VARIANT_END;
VARIANT_undo(P1);
type = P1->type;
goto __AQ_JUMP;
__AQ_OBJECT:
if (EXEC_check_operator_single(P1))
{
EXEC_operator_object_add_quick(P1, value);
goto *jump_end;
}
__AQ_BOOLEAN:
THROW(E_TYPE, "Number", TYPE_get_name(type));
__AQ_VARIANT_END:
@ -2296,27 +2161,27 @@ _SUBR_COMP:
__SC_OBJECT_FLOAT:
result = comparator_object_float(P1, P2, CO_EQUALF);
result = EXEC_comparator(OP_OBJECT_FLOAT, CO_EQUALF, P1, P2);
goto __SC_END;
__SC_FLOAT_OBJECT:
result = comparator_float_object(P1, P2, CO_EQUALF);
result = EXEC_comparator(OP_FLOAT_OBJECT, CO_EQUALF, P1, P2);
goto __SC_END;
__SC_OBJECT_CONV:
result = comparator_object_conv(P1, P2, CO_EQUAL);
result = EXEC_comparator(OP_OBJECT_CONV, CO_EQUAL, P1, P2);
goto __SC_END;
__SC_CONV_OBJECT:
result = comparator_conv_object(P1, P2, CO_EQUAL);
result = EXEC_comparator(OP_CONV_OBJECT, CO_EQUAL, P1, P2);
goto __SC_END;
__SC_OBJECT_OBJECT:
result = comparator_object(P1, P2, CO_EQUAL);
result = EXEC_comparator(OP_OBJECT_OBJECT, CO_EQUAL, P1, P2);
goto __SC_END;
__SC_VARIANT:
@ -2337,7 +2202,7 @@ _SUBR_COMP:
variant = TRUE;
}
code = check_operators(P1, P2);
code = EXEC_check_operator(P1, P2);
if (code)
{
code += T_OBJECT;
@ -2637,27 +2502,27 @@ __OBJECT:
__OBJECT_FLOAT:
result = comparator_object_float(P1, P2, CO_EQUALF);
result = EXEC_comparator(OP_OBJECT_FLOAT, CO_EQUALF, P1, P2);
goto __END;
__FLOAT_OBJECT:
result = comparator_float_object(P1, P2, CO_EQUALF);
result = EXEC_comparator(OP_FLOAT_OBJECT, CO_EQUALF, P1, P2);
goto __END;
__OBJECT_CONV:
result = comparator_object_conv(P1, P2, CO_EQUAL);
result = EXEC_comparator(OP_OBJECT_CONV, CO_EQUAL, P1, P2);
goto __END;
__CONV_OBJECT:
result = comparator_conv_object(P1, P2, CO_EQUAL);
result = EXEC_comparator(OP_CONV_OBJECT, CO_EQUAL, P1, P2);
goto __END;
__OBJECT_OBJECT:
result = comparator_object(P1, P2, CO_EQUAL);
result = EXEC_comparator(OP_OBJECT_OBJECT, CO_EQUAL, P1, P2);
goto __END;
__VARIANT:
@ -2678,7 +2543,7 @@ __VARIANT:
variant = TRUE;
}
code = check_operators(P1, P2);
code = EXEC_check_operator(P1, P2);
if (code)
{
code += T_OBJECT;
@ -2746,7 +2611,7 @@ static void my_VALUE_class_constant(CLASS *class, VALUE *value, int ind)
goto *jump[type]; \
} \
\
code = check_operators(P1, P2); \
code = EXEC_check_operator(P1, P2); \
if (code) \
{ \
code += T_DATE; \
@ -2776,7 +2641,7 @@ static void my_VALUE_class_constant(CLASS *class, VALUE *value, int ind)
return; \
} \
\
code = check_operators(P1, P2); \
code = EXEC_check_operator(P1, P2); \
if (code) \
{ \
(_func)(code + T_DATE); \
@ -2797,7 +2662,7 @@ static void my_VALUE_class_constant(CLASS *class, VALUE *value, int ind)
goto *jump[type]; \
} \
\
code = check_operators(P1, P2); \
code = EXEC_check_operator(P1, P2); \
if (code) \
{ \
code += T_POINTER; \
@ -2826,7 +2691,7 @@ static void my_VALUE_class_constant(CLASS *class, VALUE *value, int ind)
return; \
} \
\
code = check_operators(P1, P2); \
code = EXEC_check_operator(P1, P2); \
if (code) \
{ \
(_func)(code + T_POINTER); \
@ -2905,27 +2770,27 @@ __POINTER:
__OBJECT_FLOAT:
operator_object_float(P1, P2, CO_ADDF);
EXEC_operator(OP_OBJECT_FLOAT, CO_ADDF, P1, P2);
goto __END;
__FLOAT_OBJECT:
operator_float_object(P1, P2, CO_ADDF);
EXEC_operator(OP_FLOAT_OBJECT, CO_ADDF, P1, P2);
goto __END;
__OBJECT_CONV:
operator_object_conv(P1, P2, CO_ADD);
EXEC_operator(OP_OBJECT_CONV, CO_ADD, P1, P2);
goto __END;
__CONV_OBJECT:
operator_conv_object(P1, P2, CO_ADD);
EXEC_operator(OP_CONV_OBJECT, CO_ADD, P1, P2);
goto __END;
__OBJECT:
operator_object(P1, P2, CO_ADD);
EXEC_operator(OP_OBJECT_OBJECT, CO_ADD, P1, P2);
goto __END;
__VARIANT:
@ -3009,27 +2874,27 @@ __POINTER:
__OBJECT_FLOAT:
operator_object_float(P1, P2, CO_SUBF);
EXEC_operator(OP_OBJECT_FLOAT, CO_SUBF, P1, P2);
goto __END;
__FLOAT_OBJECT:
operator_float_object(P1, P2, CO_ISUBF);
EXEC_operator(OP_FLOAT_OBJECT, CO_ISUBF, P1, P2);
goto __END;
__OBJECT_CONV:
operator_object_conv(P1, P2, CO_SUB);
EXEC_operator(OP_OBJECT_CONV, CO_SUB, P1, P2);
goto __END;
__CONV_OBJECT:
operator_conv_object(P1, P2, CO_SUB);
EXEC_operator(OP_CONV_OBJECT, CO_SUB, P1, P2);
goto __END;
__OBJECT:
operator_object(P1, P2, CO_SUB);
EXEC_operator(OP_OBJECT_OBJECT, CO_SUB, P1, P2);
goto __END;
__VARIANT:
@ -3107,27 +2972,27 @@ __FLOAT:
__OBJECT_FLOAT:
operator_object_float(P1, P2, CO_MULF);
EXEC_operator(OP_OBJECT_FLOAT, CO_MULF, P1, P2);
goto __END;
__FLOAT_OBJECT:
operator_float_object(P1, P2, CO_MULF);
EXEC_operator(OP_FLOAT_OBJECT, CO_MULF, P1, P2);
goto __END;
__OBJECT_CONV:
operator_object_conv(P1, P2, CO_MUL);
EXEC_operator(OP_OBJECT_CONV, CO_MUL, P1, P2);
goto __END;
__CONV_OBJECT:
operator_conv_object(P1, P2, CO_MUL);
EXEC_operator(OP_CONV_OBJECT, CO_MUL, P1, P2);
goto __END;
__OBJECT:
operator_object(P1, P2, CO_MUL);
EXEC_operator(OP_OBJECT_OBJECT, CO_MUL, P1, P2);
goto __END;
__VARIANT:
@ -3179,27 +3044,27 @@ __FLOAT:
__OBJECT_FLOAT:
operator_object_float(P1, P2, CO_DIVF);
EXEC_operator(OP_OBJECT_FLOAT, CO_DIVF, P1, P2);
goto __CHECK_OBJECT;
__FLOAT_OBJECT:
operator_float_object(P1, P2, CO_IDIVF);
EXEC_operator(OP_FLOAT_OBJECT, CO_IDIVF, P1, P2);
goto __CHECK_OBJECT;
__OBJECT_CONV:
operator_object_conv(P1, P2, CO_DIV);
EXEC_operator(OP_OBJECT_CONV, CO_DIV, P1, P2);
goto __CHECK_OBJECT;
__CONV_OBJECT:
operator_conv_object(P1, P2, CO_DIV);
EXEC_operator(OP_CONV_OBJECT, CO_DIV, P1, P2);
goto __CHECK_OBJECT;
__OBJECT:
operator_object(P1, P2, CO_DIV);
EXEC_operator(OP_OBJECT_OBJECT, CO_DIV, P1, P2);
goto __CHECK_OBJECT;
__VARIANT:

View file

@ -0,0 +1,236 @@
/***************************************************************************
gbx_exec_operator.c
(c) 2000-2012 Benoît Minisini <gambas@users.sourceforge.net>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA.
***************************************************************************/
#define __GBX_EXEC_OPERATOR_C
#include "gb_common.h"
#include "gbx_exec.h"
typedef
void *(*FUNC_O_OF)(void *, double);
typedef
void *(*FUNC_O_OO)(void *, void *);
typedef
int (*FUNC_I_OF)(void *, double);
typedef
int (*FUNC_I_OO)(void *, void *);
typedef
void *(*FUNC_O_O)(void *);
typedef
double (*FUNC_F_O)(void *);
bool EXEC_check_operator_single(VALUE *P1)
{
return (TYPE_is_object(P1->type) && P1->_object.object && OBJECT_class(P1->_object.object)->has_operators);
}
int EXEC_check_operator(VALUE *P1, VALUE *P2)
{
if (TYPE_is_number(P1->type) && TYPE_is_object(P2->type))
{
if (P2->_object.object && OBJECT_class(P2->_object.object)->has_operators)
{
//*dynamic = P2->type == T_OBJECT;
return OP_FLOAT_OBJECT;
}
}
else if (TYPE_is_number(P2->type) && TYPE_is_object(P1->type))
{
if (P1->_object.object && OBJECT_class(P1->_object.object)->has_operators)
{
//*dynamic = P1->type == T_OBJECT;
return OP_OBJECT_FLOAT;
}
}
else if (TYPE_is_object(P1->type) && TYPE_is_object(P2->type) && P1->_object.object && P2->_object.object)
{
CLASS *class1 = OBJECT_class(P1->_object.object);
CLASS *class2 = OBJECT_class(P2->_object.object);
//*dynamic = P1->type == T_OBJECT || P2->type = T_OBJECT;
if (class1 && class1->has_operators)
{
if (class1 == class2)
return OP_OBJECT_OBJECT;
if (class2 && class2->has_operators)
return OP_OBJECT_CONV;
}
}
return OP_NOTHING;
}
void EXEC_operator(uchar what, uchar op, VALUE *P1, VALUE *P2)
{
static void *jump[] = { NULL, &&__OBJECT_FLOAT, &&__FLOAT_OBJECT, &&__OBJECT_CONV, &&__CONV_OBJECT, &&__OBJECT_OBJECT };
void *func;
void *result;
goto *jump[what];
__OBJECT_FLOAT:
if (!P1->_object.object)
THROW(E_NULL);
func = ((void **)(OBJECT_class(P1->_object.object)->operators))[op];
VALUE_conv_float(P2);
result = (*(FUNC_O_OF)func)(P1->_object.object, P2->_float.value);
OBJECT_REF(result, "EXEC_operator");
OBJECT_UNREF(P1->_object.object, "EXEC_operator");
goto __END;
__FLOAT_OBJECT:
if (!P2->_object.object)
THROW(E_NULL);
func = ((void **)(OBJECT_class(P2->_object.object)->operators))[op];
VALUE_conv_float(P1);
result = (*(FUNC_O_OF)func)(P2->_object.object, P1->_float.value);
OBJECT_REF(result, "EXEC_operator");
P1->_object.class = P2->_object.class;
OBJECT_UNREF(P2->_object.object, "EXEC_operator");
goto __END;
__OBJECT_CONV:
VALUE_conv(P2, (TYPE)P1->_object.class);
goto __OBJECT_OBJECT;
__CONV_OBJECT:
VALUE_conv(P1, (TYPE)P2->_object.class);
goto __OBJECT_OBJECT;
__OBJECT_OBJECT:
if (!P1->_object.object || !P2->_object.object)
THROW(E_NULL);
func = ((void **)(OBJECT_class(P1->_object.object)->operators))[op];
result = (*(FUNC_O_OO)func)(P1->_object.object, P2->_object.object);
OBJECT_REF(result, "EXEC_operator");
OBJECT_UNREF(P1->_object.object, "EXEC_operator");
OBJECT_UNREF(P2->_object.object, "EXEC_operator");
__END:
P1->_object.object = result;
}
void EXEC_operator_object_add_quick(VALUE *P1, double val)
{
if (P1->_object.object)
{
void *func = ((void **)(OBJECT_class(P1->_object.object)->operators))[CO_ADDF];
void *result = (*(FUNC_O_OF)func)(P1->_object.object, val);
OBJECT_REF(result, "EXEC_operator_object_float_direct");
OBJECT_UNREF(P1->_object.object, "EXEC_operator_object_float_direct");
P1->_object.object = result;
}
else
THROW(E_NULL);
}
bool EXEC_comparator(uchar what, uchar op, VALUE *P1, VALUE *P2)
{
static void *jump[] = { NULL, &&__OBJECT_FLOAT, &&__FLOAT_OBJECT, &&__OBJECT_CONV, &&__CONV_OBJECT, &&__OBJECT_OBJECT };
void *func;
int result;
goto *jump[what];
__OBJECT_FLOAT:
func = ((void **)(OBJECT_class(P1->_object.object)->operators))[op];
VALUE_conv_float(P2);
result = (*(FUNC_I_OF)func)(P1->_object.object, P2->_float.value);
OBJECT_UNREF(P1->_object.object, "EXEC_comparator");
return result;
__FLOAT_OBJECT:
func = ((void **)(OBJECT_class(P2->_object.object)->operators))[op];
VALUE_conv_float(P1);
result = (*(FUNC_I_OF)func)(P2->_object.object, P1->_float.value);
OBJECT_UNREF(P2->_object.object, "EXEC_comparator");
return result;
__OBJECT_CONV:
VALUE_conv(P2, (TYPE)P1->_object.class);
goto __OBJECT_OBJECT;
__CONV_OBJECT:
VALUE_conv(P1, (TYPE)P2->_object.class);
goto __OBJECT_OBJECT;
__OBJECT_OBJECT:
func = ((void **)(OBJECT_class(P1->_object.object)->operators))[op];
result = (*(FUNC_I_OO)func)(P1->_object.object, P2->_object.object);
OBJECT_UNREF(P1->_object.object, "EXEC_comparator");
OBJECT_UNREF(P2->_object.object, "EXEC_comparator");
return result != 0;
}
void EXEC_operator_object_abs(VALUE *P1)
{
if (P1->_object.object)
{
void *func = ((void **)(OBJECT_class(P1->_object.object)->operators))[CO_ABS];
double result = (*(FUNC_F_O)func)(P1->_object.object);
OBJECT_UNREF(P1->_object.object, "EXEC_operator_object_abs");
P1->type = T_FLOAT;
P1->_float.value = result;
}
else
THROW(E_NULL);
}
void EXEC_operator_object_single(uchar op, VALUE *P1)
{
if (P1->_object.object)
{
void *func = ((void **)(OBJECT_class(P1->_object.object)->operators))[op];
void *result = (*(FUNC_O_O)func)(P1->_object.object);
OBJECT_REF(result, "EXEC_operator_object_single");
OBJECT_UNREF(P1->_object.object, "EXEC_operator_object_single");
P1->_object.object = result;
}
else
THROW(E_NULL);
}

View file

@ -51,73 +51,6 @@
#include "gbx_subr_math_temp.h"
static bool check_operators(VALUE *P1)
{
return (TYPE_is_object(P1->type) && P1->_object.object && OBJECT_class(P1->_object.object)->has_operators);
}
static void operator_object_abs(VALUE *P1)
{
if (P1->_object.object)
{
double (*func)(void *) = (double (*)(void *))((void **)(OBJECT_class(P1->_object.object)->operators))[CO_ABS];
double result = (*func)(P1->_object.object);
OBJECT_UNREF(P1->_object.object, "operator_object_abs");
P1->type = T_FLOAT;
P1->_float.value = result;
}
else
THROW(E_NULL);
}
static void operator_object(VALUE *P1, uchar op)
{
if (P1->_object.object)
{
void *(*func)(void *) = (void *(*)(void *))((void **)(OBJECT_class(P1->_object.object)->operators))[op];
void *result = (*func)(P1->_object.object);
OBJECT_REF(result, "operator_object");
OBJECT_UNREF(P1->_object.object, "operator_object");
P1->_object.object = result;
}
else
THROW(E_NULL);
}
// TODO: merge with operator_*() functions in gbx_exec_loop.c, or move SUBR_pow() in gbx_exec_loop.c
static void operator_object_float(VALUE *P1, VALUE *P2, uchar op)
{
if (P1->_object.object)
{
void *(*func)(void *, double) = (void *(*)(void *, double))((void **)(OBJECT_class(P1->_object.object)->operators))[op];
VALUE_conv_float(P2);
void *result = (*func)(P1->_object.object, P2->_float.value);
OBJECT_REF(result, "operator_object_float");
OBJECT_UNREF(P1->_object.object, "operator_object_float");
P1->_object.object = result;
}
else
THROW(E_NULL);
}
static void operator_object_object(VALUE *P1, VALUE *P2, uchar op)
{
if (P1->_object.object && P2->_object.object)
{
void *(*func)(void *, void *) = (void *(*)(void *, void *))((void **)(OBJECT_class(P1->_object.object)->operators))[op];
void *result = (*func)(P1->_object.object, P2->_object.object);
OBJECT_REF(result, "operator_object");
OBJECT_UNREF(P1->_object.object, "operator_object");
OBJECT_UNREF(P2->_object.object, "operator_object");
P1->_object.object = result;
}
else
THROW(E_NULL);
}
void SUBR_pi(ushort code)
{
SUBR_ENTER();
@ -306,11 +239,11 @@ __VARIANT:
variant = TRUE;
}
if (check_operators(P1) && CLASS_has_operator(OBJECT_class(P1->_object.object), CO_POW))
if (EXEC_check_operator_single(P1) && CLASS_has_operator(OBJECT_class(P1->_object.object), CO_POW))
{
if (TYPE_is_number(P2->type))
type = 3;
else if (check_operators(P2) && CLASS_has_operator(OBJECT_class(P2->_object.object), CO_POW))
else if (EXEC_check_operator_single(P2) && CLASS_has_operator(OBJECT_class(P2->_object.object), CO_POW))
{
VALUE_conv(P2, (TYPE)OBJECT_class(P1->_object.object));
type = 4;
@ -324,7 +257,7 @@ __VARIANT:
type = 1;
else if (!TYPE_is_object(P2->type))
type = 2;
else if (check_operators(P2) && CLASS_has_operator(OBJECT_class(P2->_object.object), CO_POW))
else if (EXEC_check_operator_single(P2) && CLASS_has_operator(OBJECT_class(P2->_object.object), CO_POW))
{
VALUE_conv(P1, (TYPE)OBJECT_class(P2->_object.object));
type = 4;
@ -377,12 +310,12 @@ __NUMBER_FLOAT:
__OBJECT_FLOAT:
operator_object_float(P1, P2, CO_POWF);
EXEC_operator(OP_OBJECT_FLOAT, CO_POWF, P1, P2);
goto __END;
__OBJECT_OBJECT:
operator_object_object(P1, P2, CO_POW);
EXEC_operator(OP_OBJECT_OBJECT, CO_POW, P1, P2);
goto __END;
__END_NUMBER:
@ -648,7 +581,7 @@ __END:
goto *jump[type]; \
} \
\
if (check_operators(P1)) \
if (EXEC_check_operator_single(P1)) \
{ \
*PC |= T_DATE + 1; \
goto *jump[T_DATE + 1]; \
@ -664,7 +597,7 @@ __END:
VALUE_conv_variant(P1); \
return; \
} \
if (check_operators(P1)) \
if (EXEC_check_operator_single(P1)) \
{ \
(_func)(T_DATE + 1); \
VALUE_conv_variant(P1); \
@ -772,7 +705,7 @@ __FLOAT:
__OBJECT:
operator_object(P1, CO_NEG);
EXEC_operator_object_single(P1, CO_NEG);
return;
__VARIANT:
@ -830,7 +763,7 @@ __FLOAT:
__OBJECT:
operator_object_abs(P1);
EXEC_operator_object_abs(P1);
return;
__VARIANT: