[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:
parent
7d03122fa0
commit
55e313b8f5
6 changed files with 327 additions and 358 deletions
|
@ -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]"),
|
||||
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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 /* */
|
||||
|
|
|
@ -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:
|
||||
|
|
236
main/gbx/gbx_exec_operator.c
Normal file
236
main/gbx/gbx_exec_operator.c
Normal 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);
|
||||
}
|
|
@ -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:
|
||||
|
|
Loading…
Reference in a new issue