add pic_add, pic_sub, ..., pic_eq, pic_lt, ...

This commit is contained in:
Yuichi Nishiwaki 2015-07-04 09:49:00 +09:00
parent b01042505f
commit 10522b54e9
2 changed files with 91 additions and 101 deletions

View File

@ -582,6 +582,45 @@ pic_eqv_p(pic_value x, pic_value y)
#endif #endif
#if PIC_ENABLE_FLOAT
# define pic_aop(pic, a, b, op, name, guard) \
((pic_int_p(a) && pic_int_p(b)) ? \
((INT_MIN <= (double)pic_int(a) op (double)pic_int(b) && (double)pic_int(a) op (double)pic_int(b) <= INT_MAX && guard) \
? pic_int_value((int)((double)pic_int(a) op (double)pic_int(b))) \
: pic_float_value((double)pic_int(a) op (double)pic_int(b))) \
: (pic_float_p(a) && pic_float_p(b)) ? pic_float_value(pic_float(a) op pic_float(b)) \
: (pic_int_p(a) && pic_float_p(b)) ? pic_float_value(pic_int(a) op pic_float(b)) \
: (pic_float_p(a) && pic_int_p(b)) ? pic_float_value(pic_float(a) op pic_int(b)) \
: (pic_errorf(pic, name ": non-number operand given"), 0))
#else
# define pic_aop(pic, a, b, op, name) \
((pic_int_p(a) && pic_int_p(b)) \
? pic_int_value(pic_int(a) op pic_int(b)) \
: (pic_errorf(pic, name ": non-number operand given"), 0))
#endif
#define pic_add(pic, a, b) pic_aop(pic, a, b, +, "+", true)
#define pic_sub(pic, a, b) pic_aop(pic, a, b, -, "-", true)
#define pic_mul(pic, a, b) pic_aop(pic, a, b, *, "*", true)
#define pic_div(pic, a, b) pic_aop(pic, a, b, /, "/", (double)pic_int(a) / (double)pic_int(b) == round((double)pic_int(a) / (double)pic_int(b)))
#if PIC_ENABLE_FLOAT
# define pic_cmp(pic, a, b, op, name) \
((pic_int_p(a) && pic_int_p(b)) ? pic_int(a) op pic_int(b) \
: (pic_float_p(a) && pic_float_p(b)) ? pic_float(a) op pic_float(b) \
: (pic_int_p(a) && pic_float_p(b)) ? pic_int(a) op pic_float(b) \
: (pic_float_p(a) && pic_int_p(b)) ? pic_float(a) op pic_int(b) \
: (pic_errorf(pic, name ": non-number operand given"), 0))
#else
# define pic_cmp(pic, a, b, op, name) \
((pic_int_p(a) && pic_int_p(b)) ? pic_int(a) op pic_int(b) \
: (pic_errorf(pic, name ": non-number operand given"), 0))
#endif
#define pic_eq(pic, a, b) pic_cmp(pic, a, b, ==, "=")
#define pic_le(pic, a, b) pic_cmp(pic, a, b, <=, "<=")
#define pic_lt(pic, a, b) pic_cmp(pic, a, b, <, "<")
#if defined(__cplusplus) #if defined(__cplusplus)
} }
#endif #endif

View File

@ -921,111 +921,62 @@ pic_apply(pic_state *pic, struct pic_proc *proc, pic_value args)
NEXT; NEXT;
} }
#define DEFINE_ARITH_OP(opcode, op, guard) \ CASE(OP_ADD) {
CASE(opcode) { \ pic_value a, b;
pic_value a, b; \ b = POP();
b = POP(); \ a = POP();
a = POP(); \ (void)POP();
(void)POP(); \ PUSH(pic_add(pic, a, b));
if (pic_int_p(a) && pic_int_p(b)) { \ NEXT;
double f = (double)pic_int(a) op (double)pic_int(b); \
if (INT_MIN <= f && f <= INT_MAX && (guard)) { \
PUSH(pic_int_value((int)f)); \
} \
else { \
PUSH(pic_float_value(f)); \
} \
} \
else if (pic_float_p(a) && pic_float_p(b)) { \
PUSH(pic_float_value(pic_float(a) op pic_float(b))); \
} \
else if (pic_int_p(a) && pic_float_p(b)) { \
PUSH(pic_float_value(pic_int(a) op pic_float(b))); \
} \
else if (pic_float_p(a) && pic_int_p(b)) { \
PUSH(pic_float_value(pic_float(a) op pic_int(b))); \
} \
else { \
pic_errorf(pic, #op " got non-number operands"); \
} \
NEXT; \
} }
CASE(OP_SUB) {
#define DEFINE_ARITH_OP2(opcode, op) \ pic_value a, b;
CASE(opcode) { \ b = POP();
pic_value a, b; \ a = POP();
b = POP(); \ (void)POP();
a = POP(); \ PUSH(pic_sub(pic, a, b));
(void)POP(); \ NEXT;
if (pic_int_p(a) && pic_int_p(b)) { \
PUSH(pic_int_value(pic_int(a) op pic_int(b))); \
} \
else { \
pic_errorf(pic, #op " got non-number operands"); \
} \
NEXT; \
} }
CASE(OP_MUL) {
#if PIC_ENABLE_FLOAT pic_value a, b;
DEFINE_ARITH_OP(OP_ADD, +, true); b = POP();
DEFINE_ARITH_OP(OP_SUB, -, true); a = POP();
DEFINE_ARITH_OP(OP_MUL, *, true); (void)POP();
DEFINE_ARITH_OP(OP_DIV, /, f == round(f)); PUSH(pic_mul(pic, a, b));
#else NEXT;
DEFINE_ARITH_OP2(OP_ADD, +);
DEFINE_ARITH_OP2(OP_SUB, -);
DEFINE_ARITH_OP2(OP_MUL, *);
DEFINE_ARITH_OP2(OP_DIV, /);
#endif
#define DEFINE_COMP_OP(opcode, op) \
CASE(opcode) { \
pic_value a, b; \
b = POP(); \
a = POP(); \
(void)POP(); \
if (pic_int_p(a) && pic_int_p(b)) { \
PUSH(pic_bool_value(pic_int(a) op pic_int(b))); \
} \
else if (pic_float_p(a) && pic_float_p(b)) { \
PUSH(pic_bool_value(pic_float(a) op pic_float(b))); \
} \
else if (pic_int_p(a) && pic_float_p(b)) { \
PUSH(pic_bool_value(pic_int(a) op pic_float(b))); \
} \
else if (pic_float_p(a) && pic_int_p(b)) { \
PUSH(pic_bool_value(pic_float(a) op pic_int(b))); \
} \
else { \
pic_errorf(pic, #op " got non-number operands"); \
} \
NEXT; \
} }
CASE(OP_DIV) {
#define DEFINE_COMP_OP2(opcode, op) \ pic_value a, b;
CASE(opcode) { \ b = POP();
pic_value a, b; \ a = POP();
b = POP(); \ (void)POP();
a = POP(); \ PUSH(pic_div(pic, a, b));
(void)POP(); \ NEXT;
if (pic_int_p(a) && pic_int_p(b)) { \ }
PUSH(pic_bool_value(pic_int(a) op pic_int(b))); \ CASE(OP_EQ) {
} \ pic_value a, b;
else { \ b = POP();
pic_errorf(pic, #op " got non-number operands"); \ a = POP();
} \ (void)POP();
NEXT; \ PUSH(pic_bool_value(pic_eq(pic, a, b)));
NEXT;
}
CASE(OP_LE) {
pic_value a, b;
b = POP();
a = POP();
(void)POP();
PUSH(pic_bool_value(pic_le(pic, a, b)));
NEXT;
}
CASE(OP_LT) {
pic_value a, b;
b = POP();
a = POP();
(void)POP();
PUSH(pic_bool_value(pic_lt(pic, a, b)));
NEXT;
} }
#if PIC_ENABLE_FLOAT
DEFINE_COMP_OP(OP_EQ, ==);
DEFINE_COMP_OP(OP_LT, <);
DEFINE_COMP_OP(OP_LE, <=);
#else
DEFINE_COMP_OP2(OP_EQ, ==);
DEFINE_COMP_OP2(OP_LT, <);
DEFINE_COMP_OP2(OP_LE, <=);
#endif
CASE(OP_STOP) { CASE(OP_STOP) {