diff options
author | Jo-Philipp Wich <jo@mein.io> | 2022-03-06 23:56:41 +0100 |
---|---|---|
committer | Jo-Philipp Wich <jo@mein.io> | 2022-03-07 23:17:51 +0100 |
commit | efe8a0233bea283765443226340fa732cffc9ca6 (patch) | |
tree | 3532b18c9ada2e4bab1ec7d4e89e960067168c3e /vm.c | |
parent | 05bd7edd7a101aa09a54371aa34bc22646b75bee (diff) |
syntax: support add new operators
- Support ES2016 exponentiation (**) and exponentiation assignment (**=)
- Support ES2020 nullish coalescing (??) and logical nullish assignment (??=)
- Support ES2021 logical and assignment (&&=) and logical or assignment (||=)
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
Diffstat (limited to 'vm.c')
-rw-r--r-- | vm.c | 67 |
1 files changed, 67 insertions, 0 deletions
@@ -1355,6 +1355,31 @@ uc_vm_value_bitop(uc_vm_t *vm, uc_vm_insn_t operation, uc_value_t *value, uc_val } static uc_value_t * +uc_vm_value_logical(uc_vm_t *vm, uc_vm_insn_t operation, uc_value_t *value, uc_value_t *operand) +{ + uc_value_t *rv = NULL; + + switch (operation) { + case I_LTRUE: + rv = ucv_get(ucv_is_truish(value) ? operand : value); + break; + + case I_LFALSE: + rv = ucv_get(ucv_is_truish(value) ? value : operand); + break; + + case I_LNULL: + rv = ucv_get(value == NULL ? operand : value); + break; + + default: + break; + } + + return rv; +} + +static uc_value_t * uc_vm_string_concat(uc_vm_t *vm, uc_value_t *v1, uc_value_t *v2) { char buf[sizeof(void *)], *s1, *s2; @@ -1385,6 +1410,22 @@ uc_vm_string_concat(uc_vm_t *vm, uc_value_t *v1, uc_value_t *v2) return ucv_stringbuf_finish(sbuf); } +static uint64_t +upow64(uint64_t base, uint64_t exponent) +{ + uint64_t result = 1; + + while (exponent) { + if (exponent & 1) + result *= base; + + exponent >>= 1; + base *= base; + } + + return result; +} + static uc_value_t * uc_vm_value_arith(uc_vm_t *vm, uc_vm_insn_t operation, uc_value_t *value, uc_value_t *operand) { @@ -1397,6 +1438,9 @@ uc_vm_value_arith(uc_vm_t *vm, uc_vm_insn_t operation, uc_value_t *value, uc_val operation == I_BAND || operation == I_BXOR || operation == I_BOR) return uc_vm_value_bitop(vm, operation, value, operand); + if (operation == I_LTRUE || operation == I_LFALSE || operation == I_LNULL) + return uc_vm_value_logical(vm, operation, value, operand); + if (operation == I_ADD && (ucv_type(value) == UC_STRING || ucv_type(operand) == UC_STRING)) return uc_vm_string_concat(vm, value, operand); @@ -1445,6 +1489,10 @@ uc_vm_value_arith(uc_vm_t *vm, uc_vm_insn_t operation, uc_value_t *value, uc_val rv = ucv_double_new(fmod(d1, d2)); break; + case I_EXP: + rv = ucv_double_new(pow(d1, d2)); + break; + default: uc_vm_raise_exception(vm, EXCEPTION_RUNTIME, "undefined arithmetic operation %d", @@ -1549,6 +1597,24 @@ uc_vm_value_arith(uc_vm_t *vm, uc_vm_insn_t operation, uc_value_t *value, uc_val break; + case I_EXP: + if (n1 < 0 || n2 < 0) { + if (n1 < 0 && n2 < 0) + rv = ucv_double_new(-(1.0 / (double)upow64(abs64(n1), abs64(n2)))); + else if (n2 < 0) + rv = ucv_double_new(1.0 / (double)upow64(abs64(n1), abs64(n2))); + else + rv = ucv_int64_new(-upow64(abs64(n1), abs64(n2))); + } + else { + if (!u1) u1 = (uint64_t)n1; + if (!u2) u2 = (uint64_t)n2; + + rv = ucv_uint64_new(upow64(u1, u2)); + } + + break; + default: uc_vm_raise_exception(vm, EXCEPTION_RUNTIME, "undefined arithmetic operation %d", @@ -2415,6 +2481,7 @@ uc_vm_execute_chunk(uc_vm_t *vm) case I_MUL: case I_DIV: case I_MOD: + case I_EXP: uc_vm_insn_arith(vm, insn); break; |