diff options
author | Jo-Philipp Wich <jo@mein.io> | 2022-11-29 23:09:28 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-11-29 23:09:28 +0100 |
commit | cc8ae80fc0de0bf81c197e717e8523d621e9ec1f (patch) | |
tree | 0f9a074b8b4ebcb73b0487b4f2cce70ae9330857 | |
parent | 3497da1448f9b1d602e23c10977db0ce0188c959 (diff) | |
parent | eac2add08377eb4ba8e43e7e6a8f385480ebd73b (diff) |
Merge pull request #131 from jow-/fix-logical-assignment-operators-2
-rw-r--r-- | compiler.c | 132 | ||||
-rw-r--r-- | tests/custom/00_syntax/25_and_or_assignment | 78 |
2 files changed, 134 insertions, 76 deletions
@@ -575,6 +575,17 @@ uc_compiler_emit_jmp_dest(uc_compiler_t *compiler, size_t srcpos, uint32_t dest) return chunk->count - 5; } +static size_t +uc_compiler_emit_copy(uc_compiler_t *compiler, size_t srcpos, uint8_t depth) +{ + uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); + + uc_compiler_emit_insn(compiler, srcpos, I_COPY); + uc_compiler_emit_u8(compiler, 0, depth); + + return chunk->count - 2; +} + static ssize_t uc_compiler_get_jmpaddr(uc_compiler_t *compiler, size_t off) { @@ -1153,93 +1164,104 @@ static void uc_compiler_emit_variable_copy(uc_compiler_t *compiler, uc_value_t *var) { if (!var) { - uc_compiler_emit_insn(compiler, 0, I_COPY); - uc_compiler_emit_u8(compiler, 0, 1); - uc_compiler_emit_insn(compiler, 0, I_COPY); - uc_compiler_emit_u8(compiler, 0, 1); + uc_compiler_emit_copy(compiler, 0, 1); + uc_compiler_emit_copy(compiler, 0, 1); } uc_compiler_emit_variable_rw(compiler, var, 0); } static void -uc_compiler_compile_and_common(uc_compiler_t *compiler, bool assignment, uc_value_t *var) +uc_compiler_compile_and(uc_compiler_t *compiler) { uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); size_t jmpz_off; - if (assignment) - uc_compiler_emit_variable_copy(compiler, var); - - uc_compiler_emit_insn(compiler, 0, I_COPY); - uc_compiler_emit_u8(compiler, 0, 0); + uc_compiler_emit_copy(compiler, 0, 0); jmpz_off = uc_compiler_emit_jmpz(compiler, 0); uc_compiler_emit_insn(compiler, 0, I_POP); + uc_compiler_parse_precedence(compiler, P_AND); + uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count); +} - if (assignment) { - uc_compiler_parse_precedence(compiler, P_ASSIGN); - uc_compiler_emit_variable_rw(compiler, var, TK_ASSIGN); - } - else { - uc_compiler_parse_precedence(compiler, P_AND); - } +static void +uc_compiler_compile_and_assignment(uc_compiler_t *compiler, uc_value_t *var) +{ + uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); + size_t jmpz_off; + uc_compiler_emit_variable_copy(compiler, var); + uc_compiler_emit_copy(compiler, 0, 0); + jmpz_off = uc_compiler_emit_jmpz(compiler, 0); + uc_compiler_emit_insn(compiler, 0, I_POP); + uc_compiler_parse_precedence(compiler, P_ASSIGN); uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count); + uc_compiler_emit_variable_rw(compiler, var, TK_ASSIGN); } static void -uc_compiler_compile_or_common(uc_compiler_t *compiler, bool assignment, uc_value_t *var) +uc_compiler_compile_or(uc_compiler_t *compiler) { uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); size_t jmpz_off, jmp_off; - if (assignment) - uc_compiler_emit_variable_copy(compiler, var); - - uc_compiler_emit_insn(compiler, 0, I_COPY); - uc_compiler_emit_u8(compiler, 0, 0); + uc_compiler_emit_copy(compiler, 0, 0); jmpz_off = uc_compiler_emit_jmpz(compiler, 0); jmp_off = uc_compiler_emit_jmp(compiler, 0); uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count); uc_compiler_emit_insn(compiler, 0, I_POP); + uc_compiler_parse_precedence(compiler, P_OR); + uc_compiler_set_jmpaddr(compiler, jmp_off, chunk->count); +} - if (assignment) { - uc_compiler_parse_precedence(compiler, P_ASSIGN); - uc_compiler_emit_variable_rw(compiler, var, TK_ASSIGN); - } - else { - uc_compiler_parse_precedence(compiler, P_OR); - } +static void +uc_compiler_compile_or_assignment(uc_compiler_t *compiler, uc_value_t *var) +{ + uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); + size_t jmpz_off, jmp_off; + uc_compiler_emit_variable_copy(compiler, var); + jmpz_off = uc_compiler_emit_jmpz(compiler, 0); + uc_compiler_emit_variable_rw(compiler, var, 0); + jmp_off = uc_compiler_emit_jmp(compiler, 0); + uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count); + uc_compiler_parse_precedence(compiler, P_ASSIGN); + uc_compiler_emit_variable_rw(compiler, var, TK_ASSIGN); uc_compiler_set_jmpaddr(compiler, jmp_off, chunk->count); } static void -uc_compiler_compile_nullish_common(uc_compiler_t *compiler, bool assignment, uc_value_t *var) +uc_compiler_compile_nullish(uc_compiler_t *compiler) { uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); size_t jmpz_off, jmp_off; - if (assignment) - uc_compiler_emit_variable_copy(compiler, var); - - uc_compiler_emit_insn(compiler, 0, I_COPY); - uc_compiler_emit_u8(compiler, 0, 0); + uc_compiler_emit_copy(compiler, 0, 0); uc_compiler_emit_insn(compiler, 0, I_LNULL); uc_compiler_emit_insn(compiler, 0, I_NES); jmpz_off = uc_compiler_emit_jmpz(compiler, 0); jmp_off = uc_compiler_emit_jmp(compiler, 0); uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count); uc_compiler_emit_insn(compiler, 0, I_POP); + uc_compiler_parse_precedence(compiler, P_OR); + uc_compiler_set_jmpaddr(compiler, jmp_off, chunk->count); +} - if (assignment) { - uc_compiler_parse_precedence(compiler, P_ASSIGN); - uc_compiler_emit_variable_rw(compiler, var, TK_ASSIGN); - } - else { - uc_compiler_parse_precedence(compiler, P_OR); - } +static void +uc_compiler_compile_nullish_assignment(uc_compiler_t *compiler, uc_value_t *var) +{ + uc_chunk_t *chunk = uc_compiler_current_chunk(compiler); + size_t jmpz_off, jmp_off; + uc_compiler_emit_variable_copy(compiler, var); + uc_compiler_emit_insn(compiler, 0, I_LNULL); + uc_compiler_emit_insn(compiler, 0, I_NES); + jmpz_off = uc_compiler_emit_jmpz(compiler, 0); + uc_compiler_emit_variable_rw(compiler, var, 0); + jmp_off = uc_compiler_emit_jmp(compiler, 0); + uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count); + uc_compiler_parse_precedence(compiler, P_ASSIGN); + uc_compiler_emit_variable_rw(compiler, var, TK_ASSIGN); uc_compiler_set_jmpaddr(compiler, jmp_off, chunk->count); } @@ -1256,19 +1278,19 @@ uc_compiler_compile_assignment(uc_compiler_t *compiler, uc_value_t *var) if (type == TK_ASNULLISH) { uc_compiler_parse_advance(compiler); - uc_compiler_compile_nullish_common(compiler, true, var); + uc_compiler_compile_nullish_assignment(compiler, var); return true; } else if (type == TK_ASOR) { uc_compiler_parse_advance(compiler); - uc_compiler_compile_or_common(compiler, true, var); + uc_compiler_compile_or_assignment(compiler, var); return true; } else if (type == TK_ASAND) { uc_compiler_parse_advance(compiler); - uc_compiler_compile_and_common(compiler, true, var); + uc_compiler_compile_and_assignment(compiler, var); return true; } @@ -1853,24 +1875,6 @@ uc_compiler_compile_funcdecl(uc_compiler_t *compiler) } static void -uc_compiler_compile_and(uc_compiler_t *compiler) -{ - return uc_compiler_compile_and_common(compiler, false, NULL); -} - -static void -uc_compiler_compile_or(uc_compiler_t *compiler) -{ - return uc_compiler_compile_or_common(compiler, false, NULL); -} - -static void -uc_compiler_compile_nullish(uc_compiler_t *compiler) -{ - return uc_compiler_compile_nullish_common(compiler, false, NULL); -} - -static void uc_compiler_compile_dot(uc_compiler_t *compiler) { bool optional_chaining = (compiler->parser->prev.type == TK_QDOT); diff --git a/tests/custom/00_syntax/25_and_or_assignment b/tests/custom/00_syntax/25_and_or_assignment index d6a9415..114b39a 100644 --- a/tests/custom/00_syntax/25_and_or_assignment +++ b/tests/custom/00_syntax/25_and_or_assignment @@ -10,6 +10,9 @@ expression result if the lhs is truish. [ null, false, + "is truish", + null, + false, "is truish" ] -- End -- @@ -20,11 +23,23 @@ expression result if the lhs is truish. y = false; z = true; - x &&= "is truish"; - y &&= "is truish"; - z &&= "is truish"; + o = { + a: null, + b: false, + c: true + }; + + res = []; + + push(res, x &&= "is truish"); + push(res, y &&= "is truish"); + push(res, z &&= "is truish"); + + push(res, o.a &&= "is truish"); + push(res, o.b &&= "is truish"); + push(res, o.c &&= "is truish"); - printf("%.J\n", [ x, y, z ]); + printf("%.J\n", res); %} -- End -- @@ -36,6 +51,9 @@ expression result if the lhs is falsy. [ "is falsy", "is falsy", + true, + "is falsy", + "is falsy", true ] -- End -- @@ -46,11 +64,23 @@ expression result if the lhs is falsy. y = false; z = true; - x ||= "is falsy"; - y ||= "is falsy"; - z ||= "is falsy"; + o = { + a: null, + b: false, + c: true + }; + + res = []; + + push(res, x ||= "is falsy"); + push(res, y ||= "is falsy"); + push(res, z ||= "is falsy"); + + push(res, o.a ||= "is falsy"); + push(res, o.b ||= "is falsy"); + push(res, o.c ||= "is falsy"); - printf("%.J\n", [ x, y, z ]); + printf("%.J\n", res); %} -- End -- @@ -60,6 +90,15 @@ assignment condition is false. -- Expect stdout -- [ + false, + false, + true, + false, + false, + true, + 0, + 0, + 0, 0, 0, 0 @@ -71,15 +110,30 @@ assignment condition is false. a = 0; b = 0; c = 0; + d = 0; + e = 0; + f = 0; + + o = { + a: false, + b: false, + c: true + }; x = false; y = false; z = true; - x ??= a++; - y &&= b++; - z ||= c++; + res = []; + + push(res, x ??= a++); + push(res, y &&= b++); + push(res, z ||= c++); + + push(res, o.a ??= d++); + push(res, o.b &&= e++); + push(res, o.c ||= f++); - printf("%.J\n", [ a, b, c ]); + printf("%.J\n", [ ...res, a, b, c, d, e, f ]); %} -- End -- |