summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJo-Philipp Wich <jo@mein.io>2022-11-29 23:09:28 +0100
committerGitHub <noreply@github.com>2022-11-29 23:09:28 +0100
commitcc8ae80fc0de0bf81c197e717e8523d621e9ec1f (patch)
tree0f9a074b8b4ebcb73b0487b4f2cce70ae9330857
parent3497da1448f9b1d602e23c10977db0ce0188c959 (diff)
parenteac2add08377eb4ba8e43e7e6a8f385480ebd73b (diff)
Merge pull request #131 from jow-/fix-logical-assignment-operators-2
-rw-r--r--compiler.c132
-rw-r--r--tests/custom/00_syntax/25_and_or_assignment78
2 files changed, 134 insertions, 76 deletions
diff --git a/compiler.c b/compiler.c
index 6c336ae..6911477 100644
--- a/compiler.c
+++ b/compiler.c
@@ -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 --