char *JSValue_STR (JSValue val) { switch (val.tag) { case JS_NUMBER_TAG: return HPRINTF("%f", val.number); case JS_STRING_TAG: return HPRINTF("%s", val.string); case JS_BOOL_TAG: return HPRINTF("%s", val.boolean ? "true" : "false"); case JS_OBJECT_TAG: return HPRINTF("[object Object]"); case JS_FUNCTION_TAG: return HPRINTF("[function]"); default: return "null"; } }
case JS_NULL_TAG: return false; case JS_UNDEFINED_TAG: return false; default: return true; } } JS_LT_VARIANT(NUMBER_NUMBER, a.tag == JS_NUMBER_TAG && b.tag == JS_NUMBER_TAG, a.number < b.number, JSValue_NUMBER(a) < JSValue_NUMBER(b)); JS_EQ_VARIANT(NUMBER_NUMBER, a.tag == JS_NUMBER_TAG && b.tag == JS_NUMBER_TAG, a.number == b.number, JSValue_NUMBER(a) == JSValue_NUMBER(b)); JS_OR_VARIANT(BOOL_BOOL, a.tag == JS_BOOL_TAG && b.tag == JS_BOOL_TAG, a.boolean || b.boolean, JSValue_BOOL(a) || JSValue_BOOL(b)); JS_ADD_VARIANT(INT_INT, a.tag == JS_INT_TAG && b.tag == JS_INT_TAG, JS_NUMBER(a.integer + b.integer), JS_ADD_DOUBLE_DOUBLE(a, b)); JS_ADD_VARIANT(DOUBLE_DOUBLE, a.tag == JS_NUMBER_TAG && b.tag == JS_NUMBER_TAG, JS_NUMBER(a.number + b.number), JS_ADD_NUMBER_NUMBER(a, b)); JS_ADD_VARIANT(NUMBER_NUMBER, (a.tag == JS_INT_TAG || a.tag == JS_NUMBER_TAG) && (b.tag == JS_INT_TAG || b.tag == JS_NUMBER_TAG), JS_NUMBER(JSValue_NUMBER(a) + JSValue_NUMBER(b)), JS_ADD_DOUBLE_STRING(a, b)); JS_ADD_VARIANT(DOUBLE_STRING, a.tag == JS_NUMBER_TAG && b.tag == JS_STRING_TAG, JS_STRING(HPRINTF("%f%s", a.number, b.string)), JS_ADD_STRING_STRING(a, b)); JS_ADD_VARIANT(STRING_STRING, a.tag == JS_STRING_TAG && b.tag == JS_STRING_TAG, JS_STRING(HPRINTF("%s%s", a.string, b.string)), JS_STRING(HPRINTF("%s%s", JSValue_STR(a), JSValue_STR(b)))); JS_SUB_VARIANT(DOUBLE_DOUBLE, a.tag == JS_NUMBER_TAG && b.tag == JS_NUMBER_TAG, JS_NUMBER(a.number - b.number), JS_NUMBER(JSValue_NUMBER(a) - JSValue_NUMBER(b))); JS_MUL_VARIANT(DOUBLE_DOUBLE, a.tag == JS_NUMBER_TAG && b.tag == JS_NUMBER_TAG, JS_NUMBER(a.number * b.number), JS_NUMBER(JSValue_NUMBER(a) * JSValue_NUMBER(b))); JS_DIV_VARIANT(DOUBLE_DOUBLE, a.tag == JS_NUMBER_TAG && b.tag == JS_NUMBER_TAG, JS_NUMBER(a.number / b.number), JS_NUMBER(JSValue_NUMBER(a) / JSValue_NUMBER(b))); JS_MOD_VARIANT(INT_INT, a.tag == JS_INT_TAG && b.tag == JS_INT_TAG, JS_NUMBER(a.integer % b.integer), JS_MOD_DOUBLE_DOUBLE(a, b)); JS_MOD_VARIANT(DOUBLE_DOUBLE, a.tag == JS_NUMBER_TAG && b.tag == JS_NUMBER_TAG, JS_NUMBER(fmod(a.number, b.number)), JS_NUMBER(fmod(JSValue_NUMBER(a), JSValue_NUMBER(b)))); /** * Globals */
if (a.tag == JS_NUMBER_TAG && b.tag == JS_NUMBER_TAG) { *op_cache_ptr = &JS_EQ_NUMBER_NUMBER; } return ((js_op_ptr) *op_cache_ptr)(op_cache_ptr, a, b); } JS_OR_VARIANT(BOOL_BOOL, a.tag != b.tag, a.number || b.number); bool JS_OR_SWITCH (void **op_cache_ptr, JSValue a, JSValue b) { if (a.tag == JS_BOOL_TAG && b.tag == JS_BOOL_TAG) { *op_cache_ptr = &JS_OR_BOOL_BOOL; } return ((js_op_ptr) *op_cache_ptr)(op_cache_ptr, a, b); } JS_ADD_VARIANT(DOUBLE_DOUBLE, a.tag != b.tag, JS_NUMBER(a.number + b.number)); JS_ADD_VARIANT(DOUBLE_STRING, a.tag != JS_NUMBER_TAG || b.tag != JS_STRING_TAG, JS_STRING(HPRINTF("%f%s", a.number, b.string))); JSValue JS_ADD_SWITCH (void **op_cache_ptr, JSValue a, JSValue b) { if (a.tag == JS_NUMBER_TAG && b.tag == JS_NUMBER_TAG) { *op_cache_ptr = &JS_ADD_DOUBLE_DOUBLE; } else if (a.tag == JS_NUMBER_TAG && b.tag == JS_STRING_TAG) { *op_cache_ptr = &JS_ADD_DOUBLE_STRING; } return ((jsvalue_op_ptr) *op_cache_ptr)(op_cache_ptr, a, b); } JS_SUB_VARIANT(DOUBLE_DOUBLE, a.tag != b.tag, JS_NUMBER(a.number - b.number)); JSValue JS_SUB_SWITCH (void **op_cache_ptr, JSValue a, JSValue b) { if (a.tag == JS_NUMBER_TAG && b.tag == JS_NUMBER_TAG) { *op_cache_ptr = &JS_SUB_DOUBLE_DOUBLE; } return ((jsvalue_op_ptr) *op_cache_ptr)(op_cache_ptr, a, b);