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

Lib defs don't bind to each other; fix #479 again

This commit is contained in:
Nicolas Williams
2014-07-13 18:36:27 -05:00
parent cadf8c3cb0
commit c38e5b1b2c
2 changed files with 42 additions and 9 deletions

View File

@ -243,6 +243,20 @@ static int block_count_actuals(block b) {
return args;
}
static int block_count_refs(block binder, block body) {
int nrefs = 0;
for (inst* i = body.first; i; i = i->next) {
if (i != binder.first && i->bound_by == binder.first) {
nrefs++;
}
// counting recurses into closures
nrefs += block_count_refs(binder, i->subfn);
// counting recurses into argument list
nrefs += block_count_refs(binder, i->arglist);
}
return nrefs;
}
static int block_bind_subblock(block binder, block body, int bindflags) {
assert(block_is_single(binder));
assert((opcode_describe(binder.first->op)->flags & bindflags) == bindflags);
@ -274,12 +288,14 @@ static int block_bind_subblock(block binder, block body, int bindflags) {
return nrefs;
}
static void block_bind_each(block binder, block body, int bindflags) {
static int block_bind_each(block binder, block body, int bindflags) {
assert(block_has_only_binders(binder, bindflags));
bindflags |= OP_HAS_BINDING;
int nrefs = 0;
for (inst* curr = binder.first; curr; curr = curr->next) {
block_bind_subblock(inst_block(curr), body, bindflags);
nrefs += block_bind_subblock(inst_block(curr), body, bindflags);
}
return nrefs;
}
block block_bind(block binder, block body, int bindflags) {
@ -287,18 +303,35 @@ block block_bind(block binder, block body, int bindflags) {
return block_join(binder, body);
}
// Bind binder to body and throw away any defs in binder not referenced
// (directly or indirectly) from body.
block block_bind_referenced(block binder, block body, int bindflags) {
assert(block_has_only_binders(binder, bindflags));
bindflags |= OP_HAS_BINDING;
block refd = gen_noop();
for (inst* curr; (curr = block_take(&binder));) {
block b = inst_block(curr);
if (block_bind_subblock(b, body, bindflags)) {
refd = BLOCK(refd, b);
} else {
block_free(b);
block unrefd = gen_noop();
int nrefs;
for (int last_kept = 0, kept = 0; ; ) {
for (inst* curr; (curr = block_take(&binder));) {
block b = inst_block(curr);
nrefs = block_bind_each(b, body, bindflags);
// Check if this binder is referenced from any of the ones we
// already know are referenced by body.
nrefs += block_count_refs(b, refd);
if (nrefs) {
refd = BLOCK(refd, b);
kept++;
} else {
unrefd = BLOCK(unrefd, b);
}
}
if (kept == last_kept)
break;
last_kept = kept;
binder = unrefd;
unrefd = gen_noop();
}
block_free(unrefd);
return block_join(refd, body);
}

View File

@ -217,7 +217,7 @@ FuncDefs:
$$ = gen_noop();
} |
FuncDef FuncDefs {
$$ = block_join($1, $2);
$$ = block_bind($1, $2, OP_IS_CALL_PSEUDO);
}
Exp: