Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Constant fold all kinds of constants #2819

Merged
merged 2 commits into from
Aug 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 28 additions & 35 deletions src/builtin.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,15 @@ void *alloca (size_t);
#include "jv_alloc.h"


#define BINOP(name) \
static jv f_ ## name(jq_state *jq, jv input, jv a, jv b) { \
jv_free(input); \
return binop_ ## name(a, b); \
}
BINOPS
#undef BINOP


static jv type_error(jv bad, const char* msg) {
char errbuf[15];
jv err = jv_invalid_with_msg(jv_string_fmt("%s (%s) %s",
Expand Down Expand Up @@ -79,8 +88,7 @@ static inline jv ret_error2(jv bad1, jv bad2, jv msg) {
return jv_invalid_with_msg(msg);
}

static jv f_plus(jq_state *jq, jv input, jv a, jv b) {
jv_free(input);
jv binop_plus(jv a, jv b) {
if (jv_get_kind(a) == JV_KIND_NULL) {
jv_free(a);
return b;
Expand Down Expand Up @@ -312,8 +320,7 @@ static jv f_rtrimstr(jq_state *jq, jv input, jv right) {
return input;
}

static jv f_minus(jq_state *jq, jv input, jv a, jv b) {
jv_free(input);
jv binop_minus(jv a, jv b) {
if (jv_get_kind(a) == JV_KIND_NUMBER && jv_get_kind(b) == JV_KIND_NUMBER) {
jv r = jv_number(jv_number_value(a) - jv_number_value(b));
jv_free(a);
Expand Down Expand Up @@ -341,10 +348,9 @@ static jv f_minus(jq_state *jq, jv input, jv a, jv b) {
}
}

static jv f_multiply(jq_state *jq, jv input, jv a, jv b) {
jv binop_multiply(jv a, jv b) {
jv_kind ak = jv_get_kind(a);
jv_kind bk = jv_get_kind(b);
jv_free(input);
if (ak == JV_KIND_NUMBER && bk == JV_KIND_NUMBER) {
jv r = jv_number(jv_number_value(a) * jv_number_value(b));
jv_free(a);
Expand Down Expand Up @@ -380,8 +386,7 @@ static jv f_multiply(jq_state *jq, jv input, jv a, jv b) {
}
}

static jv f_divide(jq_state *jq, jv input, jv a, jv b) {
jv_free(input);
jv binop_divide(jv a, jv b) {
if (jv_get_kind(a) == JV_KIND_NUMBER && jv_get_kind(b) == JV_KIND_NUMBER) {
if (jv_number_value(b) == 0.0)
return type_error2(a, b, "cannot be divided because the divisor is zero");
Expand All @@ -397,8 +402,7 @@ static jv f_divide(jq_state *jq, jv input, jv a, jv b) {
}

#define dtoi(n) ((n) < INTMAX_MIN ? INTMAX_MIN : -(n) < INTMAX_MIN ? INTMAX_MAX : (intmax_t)(n))
static jv f_mod(jq_state *jq, jv input, jv a, jv b) {
jv_free(input);
jv binop_mod(jv a, jv b) {
if (jv_get_kind(a) == JV_KIND_NUMBER && jv_get_kind(b) == JV_KIND_NUMBER) {
double na = jv_number_value(a);
double nb = jv_number_value(b);
Expand All @@ -421,13 +425,11 @@ static jv f_mod(jq_state *jq, jv input, jv a, jv b) {
}
#undef dtoi

static jv f_equal(jq_state *jq, jv input, jv a, jv b) {
jv_free(input);
jv binop_equal(jv a, jv b) {
return jv_bool(jv_equal(a, b));
}

static jv f_notequal(jq_state *jq, jv input, jv a, jv b) {
jv_free(input);
jv binop_notequal(jv a, jv b) {
return jv_bool(!jv_equal(a, b));
}

Expand All @@ -438,29 +440,28 @@ enum cmp_op {
CMP_OP_GREATEREQ
};

static jv order_cmp(jv input, jv a, jv b, enum cmp_op op) {
jv_free(input);
static jv order_cmp(jv a, jv b, enum cmp_op op) {
int r = jv_cmp(a, b);
return jv_bool((op == CMP_OP_LESS && r < 0) ||
(op == CMP_OP_LESSEQ && r <= 0) ||
(op == CMP_OP_GREATEREQ && r >= 0) ||
(op == CMP_OP_GREATER && r > 0));
}

static jv f_less(jq_state *jq, jv input, jv a, jv b) {
return order_cmp(input, a, b, CMP_OP_LESS);
jv binop_less(jv a, jv b) {
return order_cmp(a, b, CMP_OP_LESS);
}

static jv f_greater(jq_state *jq, jv input, jv a, jv b) {
return order_cmp(input, a, b, CMP_OP_GREATER);
jv binop_greater(jv a, jv b) {
return order_cmp(a, b, CMP_OP_GREATER);
}

static jv f_lesseq(jq_state *jq, jv input, jv a, jv b) {
return order_cmp(input, a, b, CMP_OP_LESSEQ);
jv binop_lesseq(jv a, jv b) {
return order_cmp(a, b, CMP_OP_LESSEQ);
}

static jv f_greatereq(jq_state *jq, jv input, jv a, jv b) {
return order_cmp(input, a, b, CMP_OP_GREATEREQ);
jv binop_greatereq(jv a, jv b) {
return order_cmp(a, b, CMP_OP_GREATEREQ);
}

static jv f_contains(jq_state *jq, jv a, jv b) {
Expand Down Expand Up @@ -1735,12 +1736,10 @@ static const struct cfunction function_list[] = {
#ifdef HAVE_LGAMMA_R
{f_lgamma_r,"lgamma_r", 1},
#endif
{f_plus, "_plus", 3},
{f_negate, "_negate", 1},
{f_minus, "_minus", 3},
{f_multiply, "_multiply", 3},
{f_divide, "_divide", 3},
{f_mod, "_mod", 3},
#define BINOP(name) {f_ ## name, "_" #name, 3},
BINOPS
#undef BINOP
{f_dump, "tojson", 1},
{f_json_parse, "fromjson", 1},
{f_tonumber, "tonumber", 1},
Expand All @@ -1759,12 +1758,6 @@ static const struct cfunction function_list[] = {
{f_getpath, "getpath", 2},
{f_delpaths, "delpaths", 2},
{f_has, "has", 2},
{f_equal, "_equal", 3},
{f_notequal, "_notequal", 3},
{f_less, "_less", 3},
{f_greater, "_greater", 3},
{f_lesseq, "_lesseq", 3},
{f_greatereq, "_greatereq", 3},
{f_contains, "contains", 2},
{f_length, "length", 1},
{f_utf8bytelength, "utf8bytelength", 1},
Expand Down
18 changes: 18 additions & 0 deletions src/builtin.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,22 @@

int builtins_bind(jq_state *, block*);

#define BINOPS \
BINOP(plus) \
BINOP(minus) \
BINOP(multiply) \
BINOP(divide) \
BINOP(mod) \
BINOP(equal) \
BINOP(notequal) \
BINOP(less) \
BINOP(lesseq) \
BINOP(greater) \
BINOP(greatereq) \


#define BINOP(name) jv binop_ ## name(jv, jv);
BINOPS
#undef BINOP

#endif
7 changes: 7 additions & 0 deletions src/compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,13 @@ block gen_op_simple(opcode op) {
}


block gen_error(jv constant) {
assert(opcode_describe(ERRORK)->flags & OP_HAS_CONSTANT);
inst *i = inst_new(ERRORK);
i->imm.constant = constant;
return inst_block(i);
}

block gen_const(jv constant) {
assert(opcode_describe(LOADK)->flags & OP_HAS_CONSTANT);
inst* i = inst_new(LOADK);
Expand Down
1 change: 1 addition & 0 deletions src/compile.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ block gen_location(location, struct locfile*, block);
block gen_noop();
int block_is_noop(block b);
block gen_op_simple(opcode op);
block gen_error(jv constant);
block gen_const(jv constant);
block gen_const_global(jv constant, const char *name);
int block_is_const(block b);
Expand Down
6 changes: 6 additions & 0 deletions src/execute.c
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,12 @@ jv jq_next(jq_state *jq) {

case TOP: break;

case ERRORK: {
jv v = jv_array_get(jv_copy(frame_current(jq)->bc->constants), *pc++);
set_error(jq, jv_invalid_with_msg(v));
goto do_backtrack;
}

case LOADK: {
jv v = jv_array_get(jv_copy(frame_current(jq)->bc->constants), *pc++);
assert(jv_is_valid(v));
Expand Down
2 changes: 2 additions & 0 deletions src/opcode_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,5 @@ OP(GENLABEL, NONE, 0, 1)

OP(DESTRUCTURE_ALT, BRANCH, 0, 0)
OP(STOREVN, VARIABLE, 1, 0)

OP(ERRORK, CONSTANT, 1, 0)
Loading