1
0
mirror of https://github.com/stedolan/jq.git synced 2024-05-11 05:55:39 +00:00

Fold constant arrays

This commit is contained in:
Nicolas Williams
2014-08-09 20:27:08 -05:00
parent 8a561120c4
commit f87521183f

View File

@@ -499,8 +499,70 @@ block gen_both(block a, block b) {
return c;
}
block gen_const_array(block expr) {
/*
* An expr of all constant elements looks like this:
*
* 0009 FORK 0027
* 0011 FORK 0023
* 0013 FORK 0019
* 0015 LOADK 1
* 0017 JUMP 0021
* 0019 LOADK 2
* 0021 JUMP 0025
* 0023 LOADK 3
* 0025 JUMP 0029
* 0027 LOADK 4
*
* That's: N-1 commas for N elements, N LOADKs, and a JUMP between
* every LOADK. The sequence ends in a LOADK. Any deviation and it's
* not a list of constants.
*
* Here we check for this pattern almost exactly. We don't check that
* the targets of the FORK and JUMP instructions are in the right
* sequence.
*/
int all_const = 1;
int commas = 0;
int normal = 1;
jv a = jv_array();
for (inst *i = expr.first; i; i = i->next) {
if (i->op == FORK) {
commas++;
if (i->imm.target == NULL || i->imm.target->op != JUMP ||
jv_array_length(jv_copy(a)) > 0) {
normal = 0;
break;
}
} else if (all_const && i->op == LOADK) {
if (i->next != NULL && i->next->op != JUMP) {
normal = 0;
break;
}
a = jv_array_append(a, jv_copy(i->imm.constant));
} else if (i->op != JUMP || i->imm.target == NULL ||
i->imm.target->op != LOADK) {
all_const = 0;
}
}
if (all_const && normal &&
(expr.last == NULL || expr.last->op == LOADK) &&
jv_array_length(jv_copy(a)) == commas + 1) {
block_free(expr);
return gen_const(a);
}
jv_free(a);
block b = {0,0};
return b;
}
block gen_collect(block expr) {
block const_array = gen_const_array(expr);
if (const_array.first != NULL)
return const_array;
block array_var = gen_op_var_fresh(STOREV, "collect");
block c = BLOCK(gen_op_simple(DUP), gen_const(jv_array()), array_var);