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:
62
compile.c
62
compile.c
@@ -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);
|
||||
|
||||
|
Reference in New Issue
Block a user