diff --git a/compiler.c b/compiler.c index a4f220f2..b22abfc6 100644 --- a/compiler.c +++ b/compiler.c @@ -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); diff --git a/tests/custom/00_syntax/25_and_or_assignment b/tests/custom/00_syntax/25_and_or_assignment index 4dbc5f3c..d6a94157 100644 --- a/tests/custom/00_syntax/25_and_or_assignment +++ b/tests/custom/00_syntax/25_and_or_assignment @@ -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 --