Cleanup operators to use a common function
This commit is contained in:
parent
bdfb0e2221
commit
ca981fbb8e
74
src/vm.c
74
src/vm.c
@ -1072,36 +1072,43 @@ const char * krk_typeName(KrkValue value) {
|
|||||||
# define _protected
|
# define _protected
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static int _try_op(size_t methodOffset, KrkValue a, KrkValue b, KrkValue *out) {
|
||||||
|
KrkClass * type = krk_getType(a);
|
||||||
|
KrkObj * method = *(KrkObj**)((char*)type + methodOffset);
|
||||||
|
if (likely(method != NULL)) {
|
||||||
|
krk_push(a);
|
||||||
|
krk_push(b);
|
||||||
|
KrkValue result = krk_callDirect(method, 2);
|
||||||
|
if (likely(!IS_NOTIMPL(result))) {
|
||||||
|
*out = result;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION) {
|
||||||
|
*out = NONE_VAL();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static KrkValue _bin_op(size_t methodOffset, size_t invOffset, const char * operator, KrkValue a, KrkValue b) {
|
||||||
|
KrkValue result;
|
||||||
|
if (_try_op(methodOffset, a, b, &result)) return result;
|
||||||
|
if (_try_op(invOffset, b, a, &result)) return result;
|
||||||
|
return krk_runtimeError(vm.exceptions->typeError,
|
||||||
|
"unsupported operand types for %s: '%T' and '%T'",
|
||||||
|
operator, a, b);
|
||||||
|
}
|
||||||
|
|
||||||
#define MAKE_COMPARE_OP(name,operator,inv) \
|
#define MAKE_COMPARE_OP(name,operator,inv) \
|
||||||
_protected KrkValue krk_operator_ ## name (KrkValue a, KrkValue b) { \
|
_protected KrkValue krk_operator_ ## name (KrkValue a, KrkValue b) { \
|
||||||
KrkClass * atype = krk_getType(a); \
|
return _bin_op(offsetof(KrkClass,_ ## name),offsetof(KrkClass,_ ## inv), operator, a, b); \
|
||||||
if (likely(atype->_ ## name != NULL)) { \
|
|
||||||
krk_push(a); krk_push(b); \
|
|
||||||
KrkValue result = krk_callDirect(atype->_ ## name, 2); \
|
|
||||||
if (likely(!IS_NOTIMPL(result))) { return result; } \
|
|
||||||
} \
|
|
||||||
if (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION) return NONE_VAL(); \
|
|
||||||
KrkClass * btype = krk_getType(b); \
|
|
||||||
if (btype->_ ## inv) { \
|
|
||||||
krk_push(b); krk_push(a); \
|
|
||||||
KrkValue result = krk_callDirect(btype->_ ## inv, 2); \
|
|
||||||
if (likely(!IS_NOTIMPL(result))) { return result; } \
|
|
||||||
} \
|
|
||||||
if (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION) return NONE_VAL(); \
|
|
||||||
return krk_runtimeError(vm.exceptions->typeError, \
|
|
||||||
"unsupported operand types for %s: '%T' and '%T'", \
|
|
||||||
operator, a, b); \
|
|
||||||
}
|
}
|
||||||
#define MAKE_BIN_OP(name,operator,inv) \
|
#define MAKE_BIN_OP(name,operator,inv) \
|
||||||
MAKE_COMPARE_OP(name,operator,inv) \
|
MAKE_COMPARE_OP(name,operator,inv) \
|
||||||
_protected KrkValue krk_operator_i ## name (KrkValue a, KrkValue b) { \
|
_protected KrkValue krk_operator_i ## name (KrkValue a, KrkValue b) { \
|
||||||
KrkClass * atype = krk_getType(a); \
|
KrkValue result; \
|
||||||
if (likely(atype->_i ## name != NULL)) { \
|
if (_try_op(offsetof(KrkClass,_i ## name), a, b, &result)) return result; \
|
||||||
krk_push(a); krk_push(b); \
|
|
||||||
KrkValue result = krk_callDirect(atype->_i ## name, 2); \
|
|
||||||
if (!IS_NOTIMPL(result)) { return result; } \
|
|
||||||
} \
|
|
||||||
if (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION) return NONE_VAL(); \
|
|
||||||
return krk_operator_ ## name(a,b); \
|
return krk_operator_ ## name(a,b); \
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1134,15 +1141,20 @@ KrkValue krk_operator_is(KrkValue a, KrkValue b) {
|
|||||||
return BOOLEAN_VAL(krk_valuesSame(a,b));
|
return BOOLEAN_VAL(krk_valuesSame(a,b));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static KrkValue _unary_op(size_t methodOffset, const char * operator, KrkValue value) {
|
||||||
|
KrkClass * type = krk_getType(value);
|
||||||
|
KrkObj * method = *(KrkObj**)((char*)type + methodOffset);
|
||||||
|
if (likely(method != NULL)) {
|
||||||
|
krk_push(value);
|
||||||
|
return krk_callDirect(method, 1);
|
||||||
|
}
|
||||||
|
if (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION) return NONE_VAL();
|
||||||
|
return krk_runtimeError(vm.exceptions->typeError, "bad operand type for unary %s: '%T'", operator, value);
|
||||||
|
}
|
||||||
|
|
||||||
#define MAKE_UNARY_OP(sname,operator,op) \
|
#define MAKE_UNARY_OP(sname,operator,op) \
|
||||||
_protected KrkValue krk_operator_ ## operator (KrkValue value) { \
|
_protected KrkValue krk_operator_ ## operator (KrkValue value) { \
|
||||||
KrkClass * type = krk_getType(value); \
|
return _unary_op(offsetof(KrkClass,sname),#op,value); \
|
||||||
if (likely(type-> sname != NULL)) { \
|
|
||||||
krk_push(value); \
|
|
||||||
return krk_callDirect(type-> sname, 1); \
|
|
||||||
} \
|
|
||||||
if (krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION) return NONE_VAL(); \
|
|
||||||
return krk_runtimeError(vm.exceptions->typeError, "bad operand type for unary %s: '%T'", #op, value); \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MAKE_UNARY_OP(_invert,invert,~)
|
MAKE_UNARY_OP(_invert,invert,~)
|
||||||
|
Loading…
Reference in New Issue
Block a user