Skip to content

Commit

Permalink
compiler: fix ??=, ||= and &&= logical assignment operators
Browse files Browse the repository at this point in the history
When compiling logical assignment expressions, ensure that the rhs of the
assignment is not evaluated when the assignment condition is unfulfilled.

Signed-off-by: Jo-Philipp Wich <jo@mein.io>
  • Loading branch information
jow- committed Nov 14, 2022
1 parent 5fd5e8c commit bdbec19
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 1 deletion.
31 changes: 30 additions & 1 deletion compiler.c
Original file line number Diff line number Diff line change
Expand Up @@ -1161,9 +1161,38 @@ uc_compiler_compile_expression(uc_compiler_t *compiler)
static bool
uc_compiler_compile_assignment(uc_compiler_t *compiler, uc_value_t *var)
{
uc_chunk_t *chunk = uc_compiler_current_chunk(compiler);
uc_tokentype_t type = compiler->parser->curr.type;
size_t jmpz_off;

if (uc_compiler_parse_at_assignment_op(compiler)) {
if (type == TK_ASNULLISH) {
uc_compiler_parse_advance(compiler);
uc_compiler_emit_variable_rw(compiler, var, 0);
uc_compiler_emit_insn(compiler, 0, I_LNULL);
uc_compiler_emit_insn(compiler, 0, I_EQS);
jmpz_off = uc_compiler_emit_jmpz(compiler, 0);
uc_compiler_parse_precedence(compiler, P_ASSIGN);
uc_compiler_emit_variable_rw(compiler, var, type);
uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count);
}
else if (type == TK_ASOR) {
uc_compiler_parse_advance(compiler);
uc_compiler_emit_variable_rw(compiler, var, 0);
uc_compiler_emit_insn(compiler, 0, I_NOT);
jmpz_off = uc_compiler_emit_jmpz(compiler, 0);
uc_compiler_parse_precedence(compiler, P_ASSIGN);
uc_compiler_emit_variable_rw(compiler, var, type);
uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count);
}
else if (type == TK_ASAND) {
uc_compiler_parse_advance(compiler);
uc_compiler_emit_variable_rw(compiler, var, 0);
jmpz_off = uc_compiler_emit_jmpz(compiler, 0);
uc_compiler_parse_precedence(compiler, P_ASSIGN);
uc_compiler_emit_variable_rw(compiler, var, type);
uc_compiler_set_jmpaddr(compiler, jmpz_off, chunk->count);
}
else if (uc_compiler_parse_at_assignment_op(compiler)) {
uc_compiler_parse_advance(compiler);
uc_compiler_parse_precedence(compiler, P_ASSIGN);
uc_compiler_emit_variable_rw(compiler, var, type);
Expand Down
30 changes: 30 additions & 0 deletions tests/custom/00_syntax/25_and_or_assignment
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,33 @@ expression result if the lhs is falsy.
printf("%.J\n", [ x, y, z ]);
%}
-- End --


3. Ensure that the assignment value expression is not evaluated if the
assignment condition is false.

-- Expect stdout --
[
0,
0,
0
]
-- End --

-- Testcase --
{%
a = 0;
b = 0;
c = 0;

x = false;
y = false;
z = true;

x ??= a++;
y &&= b++;
z ||= c++;

printf("%.J\n", [ a, b, c ]);
%}
-- End --

0 comments on commit bdbec19

Please sign in to comment.