Skip to content

Commit

Permalink
Merge pull request #131 from jow-/fix-logical-assignment-operators-2
Browse files Browse the repository at this point in the history
  • Loading branch information
jow- authored Nov 29, 2022
2 parents 3497da1 + eac2add commit cc8ae80
Show file tree
Hide file tree
Showing 2 changed files with 134 additions and 76 deletions.
132 changes: 68 additions & 64 deletions compiler.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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);
}

Expand All @@ -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;
}
Expand Down Expand Up @@ -1852,24 +1874,6 @@ uc_compiler_compile_funcdecl(uc_compiler_t *compiler)
return uc_compiler_compile_funcexpr_common(compiler, true);
}

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)
{
Expand Down
78 changes: 66 additions & 12 deletions tests/custom/00_syntax/25_and_or_assignment
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ expression result if the lhs is truish.

-- Expect stdout --
[
null,
false,
"is truish",
null,
false,
"is truish"
Expand All @@ -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 --

Expand All @@ -34,6 +49,9 @@ expression result if the lhs is falsy.

-- Expect stdout --
[
"is falsy",
"is falsy",
true,
"is falsy",
"is falsy",
true
Expand All @@ -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 --

Expand All @@ -60,6 +90,15 @@ assignment condition is false.

-- Expect stdout --
[
false,
false,
true,
false,
false,
true,
0,
0,
0,
0,
0,
0
Expand All @@ -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 --

0 comments on commit cc8ae80

Please sign in to comment.