add functinos
This commit is contained in:
752
source/quickjs.c
752
source/quickjs.c
@@ -570,6 +570,9 @@ typedef enum MachOpcode {
|
||||
|
||||
MACH_CALLMETHOD, /* Method call: R(A)=obj, B=nargs in R(A+2)..R(A+1+B), C=cpool key */
|
||||
|
||||
MACH_EQ_TOL, /* R(A) = eq_tol(R(B), R(B+1), R(B+2)), C=3 */
|
||||
MACH_NEQ_TOL, /* R(A) = ne_tol(R(B), R(B+1), R(B+2)), C=3 */
|
||||
|
||||
MACH_NOP,
|
||||
|
||||
MACH_OP_COUNT
|
||||
@@ -632,6 +635,8 @@ static const char *mach_opcode_names[MACH_OP_COUNT] = {
|
||||
[MACH_HASPROP] = "hasprop",
|
||||
[MACH_REGEXP] = "regexp",
|
||||
[MACH_CALLMETHOD] = "callmethod",
|
||||
[MACH_EQ_TOL] = "eq_tol",
|
||||
[MACH_NEQ_TOL] = "neq_tol",
|
||||
[MACH_NOP] = "nop",
|
||||
};
|
||||
|
||||
@@ -3886,6 +3891,21 @@ static int js_string_compare_value (JSContext *ctx, JSValue op1, JSValue op2, BO
|
||||
return (len1 < len2) ? -1 : 1;
|
||||
}
|
||||
|
||||
static int js_string_compare_value_nocase (JSContext *ctx, JSValue op1, JSValue op2) {
|
||||
(void)ctx;
|
||||
int len1 = js_string_value_len (op1);
|
||||
int len2 = js_string_value_len (op2);
|
||||
if (len1 != len2) return 1;
|
||||
for (int i = 0; i < len1; i++) {
|
||||
uint32_t c1 = js_string_value_get (op1, i);
|
||||
uint32_t c2 = js_string_value_get (op2, i);
|
||||
if (c1 >= 'A' && c1 <= 'Z') c1 += 32;
|
||||
if (c2 >= 'A' && c2 <= 'Z') c2 += 32;
|
||||
if (c1 != c2) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static JSValue JS_ConcatString (JSContext *ctx, JSValue op1, JSValue op2) {
|
||||
if (unlikely (!JS_IsText (op1))) {
|
||||
op1 = JS_ToString (ctx, op1);
|
||||
@@ -28582,6 +28602,13 @@ redo:
|
||||
} else if (p[1] == '=') {
|
||||
p += 2;
|
||||
s->token_val = TOK_DIV_ASSIGN;
|
||||
} else if (p[1] == '!') {
|
||||
s->token_u.ident.str = (const char *)p;
|
||||
s->token_u.ident.len = 2;
|
||||
s->token_u.ident.has_escape = FALSE;
|
||||
s->token_u.ident.is_reserved = FALSE;
|
||||
s->token_val = TOK_IDENT;
|
||||
p += 2;
|
||||
} else {
|
||||
p++;
|
||||
s->token_val = c;
|
||||
@@ -28705,70 +28732,250 @@ redo:
|
||||
case '*':
|
||||
if (p[1] == '=') { p += 2; s->token_val = TOK_MUL_ASSIGN; }
|
||||
else if (p[1] == '*') {
|
||||
if (p[2] == '=') { p += 3; s->token_val = TOK_POW_ASSIGN; }
|
||||
if (p[2] == '!') {
|
||||
s->token_u.ident.str = (const char *)p;
|
||||
s->token_u.ident.len = 3;
|
||||
s->token_u.ident.has_escape = FALSE;
|
||||
s->token_u.ident.is_reserved = FALSE;
|
||||
s->token_val = TOK_IDENT;
|
||||
p += 3;
|
||||
}
|
||||
else if (p[2] == '=') { p += 3; s->token_val = TOK_POW_ASSIGN; }
|
||||
else { p += 2; s->token_val = TOK_POW; }
|
||||
} else { goto def_token; }
|
||||
}
|
||||
else if (p[1] == '!') {
|
||||
s->token_u.ident.str = (const char *)p;
|
||||
s->token_u.ident.len = 2;
|
||||
s->token_u.ident.has_escape = FALSE;
|
||||
s->token_u.ident.is_reserved = FALSE;
|
||||
s->token_val = TOK_IDENT;
|
||||
p += 2;
|
||||
}
|
||||
else { goto def_token; }
|
||||
break;
|
||||
case '%':
|
||||
if (p[1] == '=') { p += 2; s->token_val = TOK_MOD_ASSIGN; }
|
||||
else if (p[1] == '!') {
|
||||
s->token_u.ident.str = (const char *)p;
|
||||
s->token_u.ident.len = 2;
|
||||
s->token_u.ident.has_escape = FALSE;
|
||||
s->token_u.ident.is_reserved = FALSE;
|
||||
s->token_val = TOK_IDENT;
|
||||
p += 2;
|
||||
}
|
||||
else { goto def_token; }
|
||||
break;
|
||||
case '+':
|
||||
if (p[1] == '=') { p += 2; s->token_val = TOK_PLUS_ASSIGN; }
|
||||
else if (p[1] == '+') { p += 2; s->token_val = TOK_INC; }
|
||||
else if (p[1] == '!') {
|
||||
s->token_u.ident.str = (const char *)p;
|
||||
s->token_u.ident.len = 2;
|
||||
s->token_u.ident.has_escape = FALSE;
|
||||
s->token_u.ident.is_reserved = FALSE;
|
||||
s->token_val = TOK_IDENT;
|
||||
p += 2;
|
||||
}
|
||||
else { goto def_token; }
|
||||
break;
|
||||
case '-':
|
||||
if (p[1] == '=') { p += 2; s->token_val = TOK_MINUS_ASSIGN; }
|
||||
else if (p[1] == '-') { p += 2; s->token_val = TOK_DEC; }
|
||||
else if (p[1] == '!') {
|
||||
s->token_u.ident.str = (const char *)p;
|
||||
s->token_u.ident.len = 2;
|
||||
s->token_u.ident.has_escape = FALSE;
|
||||
s->token_u.ident.is_reserved = FALSE;
|
||||
s->token_val = TOK_IDENT;
|
||||
p += 2;
|
||||
}
|
||||
else { goto def_token; }
|
||||
break;
|
||||
case '<':
|
||||
if (p[1] == '=') { p += 2; s->token_val = TOK_LTE; }
|
||||
if (p[1] == '=' && p[2] == '!') {
|
||||
s->token_u.ident.str = (const char *)p;
|
||||
s->token_u.ident.len = 3;
|
||||
s->token_u.ident.has_escape = FALSE;
|
||||
s->token_u.ident.is_reserved = FALSE;
|
||||
s->token_val = TOK_IDENT;
|
||||
p += 3;
|
||||
}
|
||||
else if (p[1] == '=') { p += 2; s->token_val = TOK_LTE; }
|
||||
else if (p[1] == '<') {
|
||||
if (p[2] == '=') { p += 3; s->token_val = TOK_SHL_ASSIGN; }
|
||||
if (p[2] == '!') {
|
||||
s->token_u.ident.str = (const char *)p;
|
||||
s->token_u.ident.len = 3;
|
||||
s->token_u.ident.has_escape = FALSE;
|
||||
s->token_u.ident.is_reserved = FALSE;
|
||||
s->token_val = TOK_IDENT;
|
||||
p += 3;
|
||||
}
|
||||
else if (p[2] == '=') { p += 3; s->token_val = TOK_SHL_ASSIGN; }
|
||||
else { p += 2; s->token_val = TOK_SHL; }
|
||||
} else { goto def_token; }
|
||||
}
|
||||
else if (p[1] == '!') {
|
||||
s->token_u.ident.str = (const char *)p;
|
||||
s->token_u.ident.len = 2;
|
||||
s->token_u.ident.has_escape = FALSE;
|
||||
s->token_u.ident.is_reserved = FALSE;
|
||||
s->token_val = TOK_IDENT;
|
||||
p += 2;
|
||||
}
|
||||
else { goto def_token; }
|
||||
break;
|
||||
case '>':
|
||||
if (p[1] == '=') { p += 2; s->token_val = TOK_GTE; }
|
||||
if (p[1] == '=' && p[2] == '!') {
|
||||
s->token_u.ident.str = (const char *)p;
|
||||
s->token_u.ident.len = 3;
|
||||
s->token_u.ident.has_escape = FALSE;
|
||||
s->token_u.ident.is_reserved = FALSE;
|
||||
s->token_val = TOK_IDENT;
|
||||
p += 3;
|
||||
}
|
||||
else if (p[1] == '=') { p += 2; s->token_val = TOK_GTE; }
|
||||
else if (p[1] == '>') {
|
||||
if (p[2] == '>') {
|
||||
if (p[3] == '=') { p += 4; s->token_val = TOK_SHR_ASSIGN; }
|
||||
if (p[3] == '!') {
|
||||
s->token_u.ident.str = (const char *)p;
|
||||
s->token_u.ident.len = 4;
|
||||
s->token_u.ident.has_escape = FALSE;
|
||||
s->token_u.ident.is_reserved = FALSE;
|
||||
s->token_val = TOK_IDENT;
|
||||
p += 4;
|
||||
}
|
||||
else if (p[3] == '=') { p += 4; s->token_val = TOK_SHR_ASSIGN; }
|
||||
else { p += 3; s->token_val = TOK_SHR; }
|
||||
} else if (p[2] == '=') { p += 3; s->token_val = TOK_SAR_ASSIGN; }
|
||||
}
|
||||
else if (p[2] == '!') {
|
||||
s->token_u.ident.str = (const char *)p;
|
||||
s->token_u.ident.len = 3;
|
||||
s->token_u.ident.has_escape = FALSE;
|
||||
s->token_u.ident.is_reserved = FALSE;
|
||||
s->token_val = TOK_IDENT;
|
||||
p += 3;
|
||||
}
|
||||
else if (p[2] == '=') { p += 3; s->token_val = TOK_SAR_ASSIGN; }
|
||||
else { p += 2; s->token_val = TOK_SAR; }
|
||||
} else { goto def_token; }
|
||||
}
|
||||
else if (p[1] == '!') {
|
||||
s->token_u.ident.str = (const char *)p;
|
||||
s->token_u.ident.len = 2;
|
||||
s->token_u.ident.has_escape = FALSE;
|
||||
s->token_u.ident.is_reserved = FALSE;
|
||||
s->token_val = TOK_IDENT;
|
||||
p += 2;
|
||||
}
|
||||
else { goto def_token; }
|
||||
break;
|
||||
case '=':
|
||||
if (p[1] == '=') {
|
||||
if (p[2] == '=') { p += 3; s->token_val = TOK_STRICT_EQ; }
|
||||
else { p += 2; s->token_val = TOK_EQ; }
|
||||
} else if (p[1] == '>') { p += 2; s->token_val = TOK_ARROW; }
|
||||
else if (p[1] == '!') {
|
||||
s->token_u.ident.str = (const char *)p;
|
||||
s->token_u.ident.len = 2;
|
||||
s->token_u.ident.has_escape = FALSE;
|
||||
s->token_u.ident.is_reserved = FALSE;
|
||||
s->token_val = TOK_IDENT;
|
||||
p += 2;
|
||||
}
|
||||
else { goto def_token; }
|
||||
break;
|
||||
case '!':
|
||||
if (p[1] == '=') {
|
||||
if (p[2] == '=') { p += 3; s->token_val = TOK_STRICT_NEQ; }
|
||||
if (p[2] == '!') {
|
||||
s->token_u.ident.str = (const char *)p;
|
||||
s->token_u.ident.len = 3;
|
||||
s->token_u.ident.has_escape = FALSE;
|
||||
s->token_u.ident.is_reserved = FALSE;
|
||||
s->token_val = TOK_IDENT;
|
||||
p += 3;
|
||||
}
|
||||
else if (p[2] == '=') { p += 3; s->token_val = TOK_STRICT_NEQ; }
|
||||
else { p += 2; s->token_val = TOK_NEQ; }
|
||||
} else { goto def_token; }
|
||||
break;
|
||||
case '&':
|
||||
if (p[1] == '&') {
|
||||
if (p[2] == '=') { p += 3; s->token_val = TOK_LAND_ASSIGN; }
|
||||
if (p[2] == '!') {
|
||||
s->token_u.ident.str = (const char *)p;
|
||||
s->token_u.ident.len = 3;
|
||||
s->token_u.ident.has_escape = FALSE;
|
||||
s->token_u.ident.is_reserved = FALSE;
|
||||
s->token_val = TOK_IDENT;
|
||||
p += 3;
|
||||
}
|
||||
else if (p[2] == '=') { p += 3; s->token_val = TOK_LAND_ASSIGN; }
|
||||
else { p += 2; s->token_val = TOK_LAND; }
|
||||
} else if (p[1] == '=') { p += 2; s->token_val = TOK_AND_ASSIGN; }
|
||||
}
|
||||
else if (p[1] == '=') { p += 2; s->token_val = TOK_AND_ASSIGN; }
|
||||
else if (p[1] == '!') {
|
||||
s->token_u.ident.str = (const char *)p;
|
||||
s->token_u.ident.len = 2;
|
||||
s->token_u.ident.has_escape = FALSE;
|
||||
s->token_u.ident.is_reserved = FALSE;
|
||||
s->token_val = TOK_IDENT;
|
||||
p += 2;
|
||||
}
|
||||
else { goto def_token; }
|
||||
break;
|
||||
case '|':
|
||||
if (p[1] == '|') {
|
||||
if (p[2] == '=') { p += 3; s->token_val = TOK_LOR_ASSIGN; }
|
||||
if (p[2] == '!') {
|
||||
s->token_u.ident.str = (const char *)p;
|
||||
s->token_u.ident.len = 3;
|
||||
s->token_u.ident.has_escape = FALSE;
|
||||
s->token_u.ident.is_reserved = FALSE;
|
||||
s->token_val = TOK_IDENT;
|
||||
p += 3;
|
||||
}
|
||||
else if (p[2] == '=') { p += 3; s->token_val = TOK_LOR_ASSIGN; }
|
||||
else { p += 2; s->token_val = TOK_LOR; }
|
||||
} else if (p[1] == '=') { p += 2; s->token_val = TOK_OR_ASSIGN; }
|
||||
}
|
||||
else if (p[1] == '=') { p += 2; s->token_val = TOK_OR_ASSIGN; }
|
||||
else if (p[1] == '!') {
|
||||
s->token_u.ident.str = (const char *)p;
|
||||
s->token_u.ident.len = 2;
|
||||
s->token_u.ident.has_escape = FALSE;
|
||||
s->token_u.ident.is_reserved = FALSE;
|
||||
s->token_val = TOK_IDENT;
|
||||
p += 2;
|
||||
}
|
||||
else { goto def_token; }
|
||||
break;
|
||||
case '^':
|
||||
if (p[1] == '=') { p += 2; s->token_val = TOK_XOR_ASSIGN; }
|
||||
else if (p[1] == '!') {
|
||||
s->token_u.ident.str = (const char *)p;
|
||||
s->token_u.ident.len = 2;
|
||||
s->token_u.ident.has_escape = FALSE;
|
||||
s->token_u.ident.is_reserved = FALSE;
|
||||
s->token_val = TOK_IDENT;
|
||||
p += 2;
|
||||
}
|
||||
else { goto def_token; }
|
||||
break;
|
||||
case '[':
|
||||
if (p[1] == ']' && p[2] == '!') {
|
||||
s->token_u.ident.str = (const char *)p;
|
||||
s->token_u.ident.len = 3;
|
||||
s->token_u.ident.has_escape = FALSE;
|
||||
s->token_u.ident.is_reserved = FALSE;
|
||||
s->token_val = TOK_IDENT;
|
||||
p += 3;
|
||||
}
|
||||
else { goto def_token; }
|
||||
break;
|
||||
case '~':
|
||||
if (p[1] == '!') {
|
||||
s->token_u.ident.str = (const char *)p;
|
||||
s->token_u.ident.len = 2;
|
||||
s->token_u.ident.has_escape = FALSE;
|
||||
s->token_u.ident.is_reserved = FALSE;
|
||||
s->token_val = TOK_IDENT;
|
||||
p += 2;
|
||||
}
|
||||
else { goto def_token; }
|
||||
break;
|
||||
case '?':
|
||||
@@ -28905,6 +29112,13 @@ static int tokenize_next (ASTParseState *s) {
|
||||
} else if (p[1] == '=') {
|
||||
p += 2;
|
||||
s->token_val = TOK_DIV_ASSIGN;
|
||||
} else if (p[1] == '!') {
|
||||
s->token_u.ident.str = (const char *)p;
|
||||
s->token_u.ident.len = 2;
|
||||
s->token_u.ident.has_escape = FALSE;
|
||||
s->token_u.ident.is_reserved = FALSE;
|
||||
s->token_val = TOK_IDENT;
|
||||
p += 2;
|
||||
} else {
|
||||
p++;
|
||||
s->token_val = c;
|
||||
@@ -29026,70 +29240,250 @@ static int tokenize_next (ASTParseState *s) {
|
||||
case '*':
|
||||
if (p[1] == '=') { p += 2; s->token_val = TOK_MUL_ASSIGN; }
|
||||
else if (p[1] == '*') {
|
||||
if (p[2] == '=') { p += 3; s->token_val = TOK_POW_ASSIGN; }
|
||||
if (p[2] == '!') {
|
||||
s->token_u.ident.str = (const char *)p;
|
||||
s->token_u.ident.len = 3;
|
||||
s->token_u.ident.has_escape = FALSE;
|
||||
s->token_u.ident.is_reserved = FALSE;
|
||||
s->token_val = TOK_IDENT;
|
||||
p += 3;
|
||||
}
|
||||
else if (p[2] == '=') { p += 3; s->token_val = TOK_POW_ASSIGN; }
|
||||
else { p += 2; s->token_val = TOK_POW; }
|
||||
} else { goto def_token; }
|
||||
}
|
||||
else if (p[1] == '!') {
|
||||
s->token_u.ident.str = (const char *)p;
|
||||
s->token_u.ident.len = 2;
|
||||
s->token_u.ident.has_escape = FALSE;
|
||||
s->token_u.ident.is_reserved = FALSE;
|
||||
s->token_val = TOK_IDENT;
|
||||
p += 2;
|
||||
}
|
||||
else { goto def_token; }
|
||||
break;
|
||||
case '%':
|
||||
if (p[1] == '=') { p += 2; s->token_val = TOK_MOD_ASSIGN; }
|
||||
else if (p[1] == '!') {
|
||||
s->token_u.ident.str = (const char *)p;
|
||||
s->token_u.ident.len = 2;
|
||||
s->token_u.ident.has_escape = FALSE;
|
||||
s->token_u.ident.is_reserved = FALSE;
|
||||
s->token_val = TOK_IDENT;
|
||||
p += 2;
|
||||
}
|
||||
else { goto def_token; }
|
||||
break;
|
||||
case '+':
|
||||
if (p[1] == '=') { p += 2; s->token_val = TOK_PLUS_ASSIGN; }
|
||||
else if (p[1] == '+') { p += 2; s->token_val = TOK_INC; }
|
||||
else if (p[1] == '!') {
|
||||
s->token_u.ident.str = (const char *)p;
|
||||
s->token_u.ident.len = 2;
|
||||
s->token_u.ident.has_escape = FALSE;
|
||||
s->token_u.ident.is_reserved = FALSE;
|
||||
s->token_val = TOK_IDENT;
|
||||
p += 2;
|
||||
}
|
||||
else { goto def_token; }
|
||||
break;
|
||||
case '-':
|
||||
if (p[1] == '=') { p += 2; s->token_val = TOK_MINUS_ASSIGN; }
|
||||
else if (p[1] == '-') { p += 2; s->token_val = TOK_DEC; }
|
||||
else if (p[1] == '!') {
|
||||
s->token_u.ident.str = (const char *)p;
|
||||
s->token_u.ident.len = 2;
|
||||
s->token_u.ident.has_escape = FALSE;
|
||||
s->token_u.ident.is_reserved = FALSE;
|
||||
s->token_val = TOK_IDENT;
|
||||
p += 2;
|
||||
}
|
||||
else { goto def_token; }
|
||||
break;
|
||||
case '<':
|
||||
if (p[1] == '=') { p += 2; s->token_val = TOK_LTE; }
|
||||
if (p[1] == '=' && p[2] == '!') {
|
||||
s->token_u.ident.str = (const char *)p;
|
||||
s->token_u.ident.len = 3;
|
||||
s->token_u.ident.has_escape = FALSE;
|
||||
s->token_u.ident.is_reserved = FALSE;
|
||||
s->token_val = TOK_IDENT;
|
||||
p += 3;
|
||||
}
|
||||
else if (p[1] == '=') { p += 2; s->token_val = TOK_LTE; }
|
||||
else if (p[1] == '<') {
|
||||
if (p[2] == '=') { p += 3; s->token_val = TOK_SHL_ASSIGN; }
|
||||
if (p[2] == '!') {
|
||||
s->token_u.ident.str = (const char *)p;
|
||||
s->token_u.ident.len = 3;
|
||||
s->token_u.ident.has_escape = FALSE;
|
||||
s->token_u.ident.is_reserved = FALSE;
|
||||
s->token_val = TOK_IDENT;
|
||||
p += 3;
|
||||
}
|
||||
else if (p[2] == '=') { p += 3; s->token_val = TOK_SHL_ASSIGN; }
|
||||
else { p += 2; s->token_val = TOK_SHL; }
|
||||
} else { goto def_token; }
|
||||
}
|
||||
else if (p[1] == '!') {
|
||||
s->token_u.ident.str = (const char *)p;
|
||||
s->token_u.ident.len = 2;
|
||||
s->token_u.ident.has_escape = FALSE;
|
||||
s->token_u.ident.is_reserved = FALSE;
|
||||
s->token_val = TOK_IDENT;
|
||||
p += 2;
|
||||
}
|
||||
else { goto def_token; }
|
||||
break;
|
||||
case '>':
|
||||
if (p[1] == '=') { p += 2; s->token_val = TOK_GTE; }
|
||||
if (p[1] == '=' && p[2] == '!') {
|
||||
s->token_u.ident.str = (const char *)p;
|
||||
s->token_u.ident.len = 3;
|
||||
s->token_u.ident.has_escape = FALSE;
|
||||
s->token_u.ident.is_reserved = FALSE;
|
||||
s->token_val = TOK_IDENT;
|
||||
p += 3;
|
||||
}
|
||||
else if (p[1] == '=') { p += 2; s->token_val = TOK_GTE; }
|
||||
else if (p[1] == '>') {
|
||||
if (p[2] == '>') {
|
||||
if (p[3] == '=') { p += 4; s->token_val = TOK_SHR_ASSIGN; }
|
||||
if (p[3] == '!') {
|
||||
s->token_u.ident.str = (const char *)p;
|
||||
s->token_u.ident.len = 4;
|
||||
s->token_u.ident.has_escape = FALSE;
|
||||
s->token_u.ident.is_reserved = FALSE;
|
||||
s->token_val = TOK_IDENT;
|
||||
p += 4;
|
||||
}
|
||||
else if (p[3] == '=') { p += 4; s->token_val = TOK_SHR_ASSIGN; }
|
||||
else { p += 3; s->token_val = TOK_SHR; }
|
||||
} else if (p[2] == '=') { p += 3; s->token_val = TOK_SAR_ASSIGN; }
|
||||
}
|
||||
else if (p[2] == '!') {
|
||||
s->token_u.ident.str = (const char *)p;
|
||||
s->token_u.ident.len = 3;
|
||||
s->token_u.ident.has_escape = FALSE;
|
||||
s->token_u.ident.is_reserved = FALSE;
|
||||
s->token_val = TOK_IDENT;
|
||||
p += 3;
|
||||
}
|
||||
else if (p[2] == '=') { p += 3; s->token_val = TOK_SAR_ASSIGN; }
|
||||
else { p += 2; s->token_val = TOK_SAR; }
|
||||
} else { goto def_token; }
|
||||
}
|
||||
else if (p[1] == '!') {
|
||||
s->token_u.ident.str = (const char *)p;
|
||||
s->token_u.ident.len = 2;
|
||||
s->token_u.ident.has_escape = FALSE;
|
||||
s->token_u.ident.is_reserved = FALSE;
|
||||
s->token_val = TOK_IDENT;
|
||||
p += 2;
|
||||
}
|
||||
else { goto def_token; }
|
||||
break;
|
||||
case '=':
|
||||
if (p[1] == '=') {
|
||||
if (p[2] == '=') { p += 3; s->token_val = TOK_STRICT_EQ; }
|
||||
else { p += 2; s->token_val = TOK_EQ; }
|
||||
} else if (p[1] == '>') { p += 2; s->token_val = TOK_ARROW; }
|
||||
else if (p[1] == '!') {
|
||||
s->token_u.ident.str = (const char *)p;
|
||||
s->token_u.ident.len = 2;
|
||||
s->token_u.ident.has_escape = FALSE;
|
||||
s->token_u.ident.is_reserved = FALSE;
|
||||
s->token_val = TOK_IDENT;
|
||||
p += 2;
|
||||
}
|
||||
else { goto def_token; }
|
||||
break;
|
||||
case '!':
|
||||
if (p[1] == '=') {
|
||||
if (p[2] == '=') { p += 3; s->token_val = TOK_STRICT_NEQ; }
|
||||
if (p[2] == '!') {
|
||||
s->token_u.ident.str = (const char *)p;
|
||||
s->token_u.ident.len = 3;
|
||||
s->token_u.ident.has_escape = FALSE;
|
||||
s->token_u.ident.is_reserved = FALSE;
|
||||
s->token_val = TOK_IDENT;
|
||||
p += 3;
|
||||
}
|
||||
else if (p[2] == '=') { p += 3; s->token_val = TOK_STRICT_NEQ; }
|
||||
else { p += 2; s->token_val = TOK_NEQ; }
|
||||
} else { goto def_token; }
|
||||
break;
|
||||
case '&':
|
||||
if (p[1] == '&') {
|
||||
if (p[2] == '=') { p += 3; s->token_val = TOK_LAND_ASSIGN; }
|
||||
if (p[2] == '!') {
|
||||
s->token_u.ident.str = (const char *)p;
|
||||
s->token_u.ident.len = 3;
|
||||
s->token_u.ident.has_escape = FALSE;
|
||||
s->token_u.ident.is_reserved = FALSE;
|
||||
s->token_val = TOK_IDENT;
|
||||
p += 3;
|
||||
}
|
||||
else if (p[2] == '=') { p += 3; s->token_val = TOK_LAND_ASSIGN; }
|
||||
else { p += 2; s->token_val = TOK_LAND; }
|
||||
} else if (p[1] == '=') { p += 2; s->token_val = TOK_AND_ASSIGN; }
|
||||
}
|
||||
else if (p[1] == '=') { p += 2; s->token_val = TOK_AND_ASSIGN; }
|
||||
else if (p[1] == '!') {
|
||||
s->token_u.ident.str = (const char *)p;
|
||||
s->token_u.ident.len = 2;
|
||||
s->token_u.ident.has_escape = FALSE;
|
||||
s->token_u.ident.is_reserved = FALSE;
|
||||
s->token_val = TOK_IDENT;
|
||||
p += 2;
|
||||
}
|
||||
else { goto def_token; }
|
||||
break;
|
||||
case '|':
|
||||
if (p[1] == '|') {
|
||||
if (p[2] == '=') { p += 3; s->token_val = TOK_LOR_ASSIGN; }
|
||||
if (p[2] == '!') {
|
||||
s->token_u.ident.str = (const char *)p;
|
||||
s->token_u.ident.len = 3;
|
||||
s->token_u.ident.has_escape = FALSE;
|
||||
s->token_u.ident.is_reserved = FALSE;
|
||||
s->token_val = TOK_IDENT;
|
||||
p += 3;
|
||||
}
|
||||
else if (p[2] == '=') { p += 3; s->token_val = TOK_LOR_ASSIGN; }
|
||||
else { p += 2; s->token_val = TOK_LOR; }
|
||||
} else if (p[1] == '=') { p += 2; s->token_val = TOK_OR_ASSIGN; }
|
||||
}
|
||||
else if (p[1] == '=') { p += 2; s->token_val = TOK_OR_ASSIGN; }
|
||||
else if (p[1] == '!') {
|
||||
s->token_u.ident.str = (const char *)p;
|
||||
s->token_u.ident.len = 2;
|
||||
s->token_u.ident.has_escape = FALSE;
|
||||
s->token_u.ident.is_reserved = FALSE;
|
||||
s->token_val = TOK_IDENT;
|
||||
p += 2;
|
||||
}
|
||||
else { goto def_token; }
|
||||
break;
|
||||
case '^':
|
||||
if (p[1] == '=') { p += 2; s->token_val = TOK_XOR_ASSIGN; }
|
||||
else if (p[1] == '!') {
|
||||
s->token_u.ident.str = (const char *)p;
|
||||
s->token_u.ident.len = 2;
|
||||
s->token_u.ident.has_escape = FALSE;
|
||||
s->token_u.ident.is_reserved = FALSE;
|
||||
s->token_val = TOK_IDENT;
|
||||
p += 2;
|
||||
}
|
||||
else { goto def_token; }
|
||||
break;
|
||||
case '[':
|
||||
if (p[1] == ']' && p[2] == '!') {
|
||||
s->token_u.ident.str = (const char *)p;
|
||||
s->token_u.ident.len = 3;
|
||||
s->token_u.ident.has_escape = FALSE;
|
||||
s->token_u.ident.is_reserved = FALSE;
|
||||
s->token_val = TOK_IDENT;
|
||||
p += 3;
|
||||
}
|
||||
else { goto def_token; }
|
||||
break;
|
||||
case '~':
|
||||
if (p[1] == '!') {
|
||||
s->token_u.ident.str = (const char *)p;
|
||||
s->token_u.ident.len = 2;
|
||||
s->token_u.ident.has_escape = FALSE;
|
||||
s->token_u.ident.is_reserved = FALSE;
|
||||
s->token_val = TOK_IDENT;
|
||||
p += 2;
|
||||
}
|
||||
else { goto def_token; }
|
||||
break;
|
||||
case '?':
|
||||
@@ -30491,6 +30885,18 @@ static int ast_sem_in_loop (ASTSemScope *scope) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BOOL is_functino_name(const char *name) {
|
||||
static const char *functinos[] = {
|
||||
"+!", "-!", "*!", "/!", "%!", "**!",
|
||||
"<!", ">!", "<=!", ">=!", "=!", "!=!",
|
||||
"&!", "|!", "^!", "<<!", ">>!", ">>>!",
|
||||
"&&!", "||!", "~!", "[]!", NULL
|
||||
};
|
||||
for (int i = 0; functinos[i]; i++)
|
||||
if (strcmp(name, functinos[i]) == 0) return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void ast_sem_check_expr (ASTSemState *st, ASTSemScope *scope, cJSON *expr);
|
||||
static void ast_sem_check_stmt (ASTSemState *st, ASTSemScope *scope, cJSON *stmt);
|
||||
|
||||
@@ -30743,6 +31149,11 @@ static void ast_sem_check_expr (ASTSemState *st, ASTSemScope *scope, cJSON *expr
|
||||
if (strcmp (kind, "name") == 0) {
|
||||
const char *name = cJSON_GetStringValue (cJSON_GetObjectItemCaseSensitive (expr, "name"));
|
||||
if (name) {
|
||||
if (is_functino_name(name)) {
|
||||
cJSON_AddStringToObject (expr, "make", "functino");
|
||||
cJSON_AddNumberToObject (expr, "level", -1);
|
||||
return;
|
||||
}
|
||||
ASTSemLookup r = ast_sem_lookup_var (scope, name);
|
||||
if (r.var) {
|
||||
cJSON_AddNumberToObject (expr, "level", r.level);
|
||||
@@ -31701,6 +32112,111 @@ static int mach_compile_expr(MachCompState *cs, cJSON *node, int dest) {
|
||||
if (fn_expr)
|
||||
fn_kind = cJSON_GetStringValue(cJSON_GetObjectItemCaseSensitive(fn_expr, "kind"));
|
||||
|
||||
/* Functino: inline operator call */
|
||||
if (fn_kind && strcmp(fn_kind, "name") == 0) {
|
||||
const char *fn_make = cJSON_GetStringValue(cJSON_GetObjectItemCaseSensitive(fn_expr, "make"));
|
||||
if (fn_make && strcmp(fn_make, "functino") == 0) {
|
||||
const char *fname = cJSON_GetStringValue(cJSON_GetObjectItemCaseSensitive(fn_expr, "name"));
|
||||
if (dest < 0) dest = mach_reserve_reg(cs);
|
||||
|
||||
if (strcmp(fname, "~!") == 0) {
|
||||
int save = cs->freereg;
|
||||
int r = mach_compile_expr(cs, cJSON_GetArrayItem(args, 0), -1);
|
||||
mach_emit(cs, MACH_ABC(MACH_BNOT, dest, r, 0));
|
||||
mach_free_reg_to(cs, save);
|
||||
return dest;
|
||||
}
|
||||
if (strcmp(fname, "[]!") == 0) {
|
||||
int save = cs->freereg;
|
||||
int r0 = mach_compile_expr(cs, cJSON_GetArrayItem(args, 0), -1);
|
||||
if (cs->freereg <= r0) cs->freereg = r0 + 1;
|
||||
int r1 = mach_compile_expr(cs, cJSON_GetArrayItem(args, 1), -1);
|
||||
mach_emit(cs, MACH_ABC(MACH_GETINDEX, dest, r0, r1));
|
||||
mach_free_reg_to(cs, save);
|
||||
return dest;
|
||||
}
|
||||
if ((strcmp(fname, "=!") == 0 || strcmp(fname, "!=!") == 0) && nargs == 3) {
|
||||
int save = cs->freereg;
|
||||
int base = mach_reserve_reg(cs);
|
||||
int r0 = mach_compile_expr(cs, cJSON_GetArrayItem(args, 0), base);
|
||||
if (r0 != base) mach_emit(cs, MACH_ABC(MACH_MOVE, base, r0, 0));
|
||||
int r1_reg = mach_reserve_reg(cs);
|
||||
int r1 = mach_compile_expr(cs, cJSON_GetArrayItem(args, 1), r1_reg);
|
||||
if (r1 != r1_reg) mach_emit(cs, MACH_ABC(MACH_MOVE, r1_reg, r1, 0));
|
||||
int r2_reg = mach_reserve_reg(cs);
|
||||
int r2 = mach_compile_expr(cs, cJSON_GetArrayItem(args, 2), r2_reg);
|
||||
if (r2 != r2_reg) mach_emit(cs, MACH_ABC(MACH_MOVE, r2_reg, r2, 0));
|
||||
MachOpcode top = (strcmp(fname, "=!") == 0) ? MACH_EQ_TOL : MACH_NEQ_TOL;
|
||||
mach_emit(cs, MACH_ABC(top, dest, base, 3));
|
||||
mach_free_reg_to(cs, save);
|
||||
return dest;
|
||||
}
|
||||
if (strcmp(fname, "&&!") == 0) {
|
||||
int save = cs->freereg;
|
||||
int r0 = mach_compile_expr(cs, cJSON_GetArrayItem(args, 0), -1);
|
||||
if (cs->freereg <= r0) cs->freereg = r0 + 1;
|
||||
int r1 = mach_compile_expr(cs, cJSON_GetArrayItem(args, 1), -1);
|
||||
/* Non-short-circuiting: if left is falsy, result=left, else result=right */
|
||||
mach_emit(cs, MACH_ABC(MACH_MOVE, dest, r0, 0));
|
||||
int jmp_pc = mach_current_pc(cs);
|
||||
mach_emit(cs, MACH_AsBx(MACH_JMPFALSE, dest, 0));
|
||||
mach_emit(cs, MACH_ABC(MACH_MOVE, dest, r1, 0));
|
||||
{
|
||||
int offset = mach_current_pc(cs) - (jmp_pc + 1);
|
||||
cs->code[jmp_pc] = MACH_AsBx(MACH_GET_OP(cs->code[jmp_pc]), dest, (int16_t)offset);
|
||||
}
|
||||
mach_free_reg_to(cs, save);
|
||||
return dest;
|
||||
}
|
||||
if (strcmp(fname, "||!") == 0) {
|
||||
int save = cs->freereg;
|
||||
int r0 = mach_compile_expr(cs, cJSON_GetArrayItem(args, 0), -1);
|
||||
if (cs->freereg <= r0) cs->freereg = r0 + 1;
|
||||
int r1 = mach_compile_expr(cs, cJSON_GetArrayItem(args, 1), -1);
|
||||
/* Non-short-circuiting: if left is truthy, result=left, else result=right */
|
||||
mach_emit(cs, MACH_ABC(MACH_MOVE, dest, r0, 0));
|
||||
int jmp_pc = mach_current_pc(cs);
|
||||
mach_emit(cs, MACH_AsBx(MACH_JMPTRUE, dest, 0));
|
||||
mach_emit(cs, MACH_ABC(MACH_MOVE, dest, r1, 0));
|
||||
{
|
||||
int offset = mach_current_pc(cs) - (jmp_pc + 1);
|
||||
cs->code[jmp_pc] = MACH_AsBx(MACH_GET_OP(cs->code[jmp_pc]), dest, (int16_t)offset);
|
||||
}
|
||||
mach_free_reg_to(cs, save);
|
||||
return dest;
|
||||
}
|
||||
/* Standard 2-arg binary functino */
|
||||
{
|
||||
int save = cs->freereg;
|
||||
int r0 = mach_compile_expr(cs, cJSON_GetArrayItem(args, 0), -1);
|
||||
if (cs->freereg <= r0) cs->freereg = r0 + 1;
|
||||
int r1 = mach_compile_expr(cs, cJSON_GetArrayItem(args, 1), -1);
|
||||
MachOpcode op;
|
||||
if (strcmp(fname, "+!") == 0) op = MACH_ADD;
|
||||
else if (strcmp(fname, "-!") == 0) op = MACH_SUB;
|
||||
else if (strcmp(fname, "*!") == 0) op = MACH_MUL;
|
||||
else if (strcmp(fname, "/!") == 0) op = MACH_DIV;
|
||||
else if (strcmp(fname, "%!") == 0) op = MACH_MOD;
|
||||
else if (strcmp(fname, "**!") == 0) op = MACH_POW;
|
||||
else if (strcmp(fname, "<!") == 0) op = MACH_LT;
|
||||
else if (strcmp(fname, ">!") == 0) op = MACH_GT;
|
||||
else if (strcmp(fname, "<=!") == 0) op = MACH_LE;
|
||||
else if (strcmp(fname, ">=!") == 0) op = MACH_GE;
|
||||
else if (strcmp(fname, "=!") == 0) op = MACH_EQ;
|
||||
else if (strcmp(fname, "!=!") == 0) op = MACH_NEQ;
|
||||
else if (strcmp(fname, "&!") == 0) op = MACH_BAND;
|
||||
else if (strcmp(fname, "|!") == 0) op = MACH_BOR;
|
||||
else if (strcmp(fname, "^!") == 0) op = MACH_BXOR;
|
||||
else if (strcmp(fname, "<<!") == 0) op = MACH_SHL;
|
||||
else if (strcmp(fname, ">>!") == 0) op = MACH_SHR;
|
||||
else op = MACH_USHR; /* >>>! */
|
||||
mach_emit(cs, MACH_ABC(op, dest, r0, r1));
|
||||
mach_free_reg_to(cs, save);
|
||||
return dest;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fn_kind && strcmp(fn_kind, ".") == 0) {
|
||||
/* Method call with dot notation: obj.method(args) */
|
||||
int save_freereg = cs->freereg;
|
||||
@@ -33479,6 +33995,33 @@ static JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
|
||||
break;
|
||||
}
|
||||
|
||||
case MACH_EQ_TOL:
|
||||
case MACH_NEQ_TOL: {
|
||||
/* A=dest, B=base, C=3; args in R(B), R(B+1), R(B+2) */
|
||||
JSValue left = frame->slots[b];
|
||||
JSValue right = frame->slots[b + 1];
|
||||
JSValue tol = frame->slots[b + 2];
|
||||
BOOL is_eq_op = (op == MACH_EQ_TOL);
|
||||
if (JS_IsNumber(left) && JS_IsNumber(right) && JS_IsNumber(tol)) {
|
||||
double da, db, dt;
|
||||
JS_ToFloat64(ctx, &da, left);
|
||||
JS_ToFloat64(ctx, &db, right);
|
||||
JS_ToFloat64(ctx, &dt, tol);
|
||||
BOOL eq = fabs(da - db) <= dt;
|
||||
frame->slots[a] = JS_NewBool(ctx, is_eq_op ? eq : !eq);
|
||||
} else if (JS_IsText(left) && JS_IsText(right) && JS_VALUE_GET_TAG(tol) == JS_TAG_BOOL && JS_VALUE_GET_BOOL(tol)) {
|
||||
BOOL eq = js_string_compare_value_nocase(ctx, left, right) == 0;
|
||||
frame->slots[a] = JS_NewBool(ctx, is_eq_op ? eq : !eq);
|
||||
} else {
|
||||
/* Fall through to standard eq/neq */
|
||||
JSValue res = reg_vm_binop(ctx, is_eq_op ? MACH_EQ : MACH_NEQ, left, right);
|
||||
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
|
||||
if (JS_IsException(res)) { goto disrupt; }
|
||||
frame->slots[a] = res;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case MACH_NEG: {
|
||||
JSValue v = frame->slots[b];
|
||||
if (JS_IsInt(v)) {
|
||||
@@ -34288,6 +34831,16 @@ static void mach_gen_emit_3 (MachGenState *s, const char *op, int a, int b, int
|
||||
mach_gen_add_instr (s, instr);
|
||||
}
|
||||
|
||||
static void mach_gen_emit_4 (MachGenState *s, const char *op, int a, int b, int c, int d) {
|
||||
cJSON *instr = cJSON_CreateArray ();
|
||||
cJSON_AddItemToArray (instr, cJSON_CreateString (op));
|
||||
cJSON_AddItemToArray (instr, cJSON_CreateNumber (a));
|
||||
cJSON_AddItemToArray (instr, cJSON_CreateNumber (b));
|
||||
cJSON_AddItemToArray (instr, cJSON_CreateNumber (c));
|
||||
cJSON_AddItemToArray (instr, cJSON_CreateNumber (d));
|
||||
mach_gen_add_instr (s, instr);
|
||||
}
|
||||
|
||||
static void mach_gen_emit_const_num (MachGenState *s, int dest, double val) {
|
||||
cJSON *instr = cJSON_CreateArray ();
|
||||
cJSON_AddItemToArray (instr, cJSON_CreateString ("access"));
|
||||
@@ -34428,6 +34981,32 @@ static void mach_gen_emit_go_call_method (MachGenState *s, int obj, const char *
|
||||
mach_gen_emit_1 (s, "goinvoke", frame_slot);
|
||||
}
|
||||
|
||||
static const char *functino_to_mcode_op (const char *name) {
|
||||
if (strcmp (name, "+!") == 0) return "add";
|
||||
if (strcmp (name, "-!") == 0) return "subtract";
|
||||
if (strcmp (name, "*!") == 0) return "multiply";
|
||||
if (strcmp (name, "/!") == 0) return "divide";
|
||||
if (strcmp (name, "%!") == 0) return "modulo";
|
||||
if (strcmp (name, "**!") == 0) return "pow";
|
||||
if (strcmp (name, "<!") == 0) return "lt";
|
||||
if (strcmp (name, ">!") == 0) return "gt";
|
||||
if (strcmp (name, "<=!") == 0) return "le";
|
||||
if (strcmp (name, ">=!") == 0) return "ge";
|
||||
if (strcmp (name, "=!") == 0) return "eq";
|
||||
if (strcmp (name, "!=!") == 0) return "ne";
|
||||
if (strcmp (name, "&!") == 0) return "bitand";
|
||||
if (strcmp (name, "|!") == 0) return "bitor";
|
||||
if (strcmp (name, "^!") == 0) return "bitxor";
|
||||
if (strcmp (name, "<<!") == 0) return "shl";
|
||||
if (strcmp (name, ">>!") == 0) return "shr";
|
||||
if (strcmp (name, ">>>!") == 0) return "ushr";
|
||||
if (strcmp (name, "&&!") == 0) return "and";
|
||||
if (strcmp (name, "||!") == 0) return "or";
|
||||
if (strcmp (name, "~!") == 0) return "bitnot";
|
||||
if (strcmp (name, "[]!") == 0) return "load";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char *mach_gen_binop_to_string (const char *kind) {
|
||||
if (strcmp (kind, "+") == 0) return "add";
|
||||
if (strcmp (kind, "-") == 0) return "subtract";
|
||||
@@ -34828,13 +35407,69 @@ static int mach_gen_expr (MachGenState *s, cJSON *expr, int target) {
|
||||
if (strcmp (kind, "(") == 0) {
|
||||
cJSON *callee = cJSON_GetObjectItemCaseSensitive (expr, "expression");
|
||||
cJSON *args_list = cJSON_GetObjectItemCaseSensitive (expr, "list");
|
||||
|
||||
/* Functino: inline operator call */
|
||||
const char *callee_kind = cJSON_GetStringValue (cJSON_GetObjectItemCaseSensitive (callee, "kind"));
|
||||
if (callee_kind && strcmp (callee_kind, "name") == 0) {
|
||||
const char *callee_make = cJSON_GetStringValue (cJSON_GetObjectItemCaseSensitive (callee, "make"));
|
||||
if (callee_make && strcmp (callee_make, "functino") == 0) {
|
||||
const char *fname = cJSON_GetStringValue (cJSON_GetObjectItemCaseSensitive (callee, "name"));
|
||||
const char *mop = functino_to_mcode_op (fname);
|
||||
int nargs = args_list ? cJSON_GetArraySize (args_list) : 0;
|
||||
|
||||
if (strcmp (fname, "~!") == 0) {
|
||||
int a0 = mach_gen_expr (s, cJSON_GetArrayItem (args_list, 0), -1);
|
||||
int d = mach_gen_alloc_slot (s);
|
||||
mach_gen_emit_2 (s, mop, d, a0);
|
||||
return d;
|
||||
}
|
||||
if (strcmp (fname, "[]!") == 0) {
|
||||
int a0 = mach_gen_expr (s, cJSON_GetArrayItem (args_list, 0), -1);
|
||||
int a1 = mach_gen_expr (s, cJSON_GetArrayItem (args_list, 1), -1);
|
||||
int d = mach_gen_alloc_slot (s);
|
||||
mach_gen_emit_get_elem (s, d, a0, a1);
|
||||
return d;
|
||||
}
|
||||
if ((strcmp (fname, "=!") == 0 || strcmp (fname, "!=!") == 0) && nargs == 3) {
|
||||
int a0 = mach_gen_expr (s, cJSON_GetArrayItem (args_list, 0), -1);
|
||||
int a1 = mach_gen_expr (s, cJSON_GetArrayItem (args_list, 1), -1);
|
||||
int a2 = mach_gen_expr (s, cJSON_GetArrayItem (args_list, 2), -1);
|
||||
int d = mach_gen_alloc_slot (s);
|
||||
const char *top = (strcmp (fname, "=!") == 0) ? "eq_tol" : "ne_tol";
|
||||
mach_gen_emit_4 (s, top, d, a0, a1, a2);
|
||||
return d;
|
||||
}
|
||||
if (strcmp (fname, "&&!") == 0) {
|
||||
int a0 = mach_gen_expr (s, cJSON_GetArrayItem (args_list, 0), -1);
|
||||
int a1 = mach_gen_expr (s, cJSON_GetArrayItem (args_list, 1), -1);
|
||||
int d = mach_gen_alloc_slot (s);
|
||||
mach_gen_emit_3 (s, "and", d, a0, a1);
|
||||
return d;
|
||||
}
|
||||
if (strcmp (fname, "||!") == 0) {
|
||||
int a0 = mach_gen_expr (s, cJSON_GetArrayItem (args_list, 0), -1);
|
||||
int a1 = mach_gen_expr (s, cJSON_GetArrayItem (args_list, 1), -1);
|
||||
int d = mach_gen_alloc_slot (s);
|
||||
mach_gen_emit_3 (s, "or", d, a0, a1);
|
||||
return d;
|
||||
}
|
||||
/* Standard 2-arg binary functino */
|
||||
{
|
||||
int a0 = mach_gen_expr (s, cJSON_GetArrayItem (args_list, 0), -1);
|
||||
int a1 = mach_gen_expr (s, cJSON_GetArrayItem (args_list, 1), -1);
|
||||
int d = mach_gen_alloc_slot (s);
|
||||
mach_gen_emit_3 (s, mop, d, a0, a1);
|
||||
return d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cJSON *arg_slots = cJSON_CreateArray ();
|
||||
cJSON *arg;
|
||||
cJSON_ArrayForEach (arg, args_list) {
|
||||
int arg_slot = mach_gen_expr (s, arg, -1);
|
||||
cJSON_AddItemToArray (arg_slots, cJSON_CreateNumber (arg_slot));
|
||||
}
|
||||
const char *callee_kind = cJSON_GetStringValue (cJSON_GetObjectItemCaseSensitive (callee, "kind"));
|
||||
int dest = mach_gen_alloc_slot (s);
|
||||
if (strcmp (callee_kind, ".") == 0) {
|
||||
cJSON *obj = cJSON_GetObjectItemCaseSensitive (callee, "left");
|
||||
@@ -36317,6 +36952,61 @@ static JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj,
|
||||
frame->slots[dest] = JS_TRUE;
|
||||
}
|
||||
}
|
||||
else if (strcmp(op, "eq_tol") == 0) {
|
||||
int dest = (int)a1->valuedouble;
|
||||
JSValue left = frame->slots[(int)a2->valuedouble];
|
||||
JSValue right = frame->slots[(int)a3->valuedouble];
|
||||
cJSON *a4 = cJSON_GetArrayItem(instr, 4);
|
||||
JSValue tol = frame->slots[(int)a4->valuedouble];
|
||||
if (JS_IsNumber(left) && JS_IsNumber(right) && JS_IsNumber(tol)) {
|
||||
double a, b, t;
|
||||
JS_ToFloat64(ctx, &a, left);
|
||||
JS_ToFloat64(ctx, &b, right);
|
||||
JS_ToFloat64(ctx, &t, tol);
|
||||
frame->slots[dest] = JS_NewBool(ctx, fabs(a - b) <= t);
|
||||
} else if (JS_IsText(left) && JS_IsText(right) && JS_VALUE_GET_TAG(tol) == JS_TAG_BOOL && JS_VALUE_GET_BOOL(tol)) {
|
||||
frame->slots[dest] = JS_NewBool(ctx, js_string_compare_value_nocase(ctx, left, right) == 0);
|
||||
} else {
|
||||
/* Fall through to standard eq */
|
||||
if (left == right) frame->slots[dest] = JS_TRUE;
|
||||
else if (JS_IsText(left) && JS_IsText(right))
|
||||
frame->slots[dest] = JS_NewBool(ctx, js_string_compare_value(ctx, left, right, TRUE) == 0);
|
||||
else frame->slots[dest] = JS_FALSE;
|
||||
}
|
||||
}
|
||||
else if (strcmp(op, "ne_tol") == 0) {
|
||||
int dest = (int)a1->valuedouble;
|
||||
JSValue left = frame->slots[(int)a2->valuedouble];
|
||||
JSValue right = frame->slots[(int)a3->valuedouble];
|
||||
cJSON *a4 = cJSON_GetArrayItem(instr, 4);
|
||||
JSValue tol = frame->slots[(int)a4->valuedouble];
|
||||
if (JS_IsNumber(left) && JS_IsNumber(right) && JS_IsNumber(tol)) {
|
||||
double a, b, t;
|
||||
JS_ToFloat64(ctx, &a, left);
|
||||
JS_ToFloat64(ctx, &b, right);
|
||||
JS_ToFloat64(ctx, &t, tol);
|
||||
frame->slots[dest] = JS_NewBool(ctx, fabs(a - b) > t);
|
||||
} else if (JS_IsText(left) && JS_IsText(right) && JS_VALUE_GET_TAG(tol) == JS_TAG_BOOL && JS_VALUE_GET_BOOL(tol)) {
|
||||
frame->slots[dest] = JS_NewBool(ctx, js_string_compare_value_nocase(ctx, left, right) != 0);
|
||||
} else {
|
||||
if (left == right) frame->slots[dest] = JS_FALSE;
|
||||
else if (JS_IsText(left) && JS_IsText(right))
|
||||
frame->slots[dest] = JS_NewBool(ctx, js_string_compare_value(ctx, left, right, TRUE) != 0);
|
||||
else frame->slots[dest] = JS_TRUE;
|
||||
}
|
||||
}
|
||||
else if (strcmp(op, "and") == 0) {
|
||||
int dest = (int)a1->valuedouble;
|
||||
JSValue left = frame->slots[(int)a2->valuedouble];
|
||||
JSValue right = frame->slots[(int)a3->valuedouble];
|
||||
frame->slots[dest] = JS_ToBool(ctx, left) ? right : left;
|
||||
}
|
||||
else if (strcmp(op, "or") == 0) {
|
||||
int dest = (int)a1->valuedouble;
|
||||
JSValue left = frame->slots[(int)a2->valuedouble];
|
||||
JSValue right = frame->slots[(int)a3->valuedouble];
|
||||
frame->slots[dest] = JS_ToBool(ctx, left) ? left : right;
|
||||
}
|
||||
else if (strcmp(op, "lt") == 0) {
|
||||
int dest = (int)a1->valuedouble;
|
||||
JSValue left = frame->slots[(int)a2->valuedouble];
|
||||
@@ -37561,6 +38251,10 @@ static void dump_register_code(JSContext *ctx, JSCodeRegister *code, int indent)
|
||||
printf("r%d, r%d, r%d", a, b, c);
|
||||
break;
|
||||
|
||||
case MACH_EQ_TOL: case MACH_NEQ_TOL:
|
||||
printf("r%d, r%d, %d", a, b, c);
|
||||
break;
|
||||
|
||||
/* Property access */
|
||||
case MACH_GETFIELD:
|
||||
printf("r%d, r%d, #%d", a, b, c);
|
||||
|
||||
Reference in New Issue
Block a user