don't allocate a new arena in h_bind, use the existing one

Rationale: If memory allocation fails in the inner parse and we
longjump up the stack, the temporary arena will be missed and leak.

NB: This change means that any allocations done by the continuation
(in the form of new parsers, probably) will persist for the
lifetime of the parse result. Beware of wasting too much memory
this way! The bind continuation should generally keep dynamic
allocations to a minimum.
This commit is contained in:
Sven M. Hallberg 2015-11-30 14:19:40 +01:00
parent e26a8ff572
commit ca1d8df06c

View file

@ -4,7 +4,6 @@ typedef struct {
const HParser *p;
HContinuation k;
void *env;
HAllocator *mm__;
} BindEnv;
// an HAllocator backed by an HArena
@ -39,20 +38,15 @@ static HParseResult *parse_bind(void *be_, HParseState *state) {
if(!res)
return NULL;
// create a temporary arena allocator for the continuation
HArena *arena = h_new_arena(be->mm__, 0);
ArenaAllocator aa = {{aa_alloc, aa_realloc, aa_free}, arena};
// create a wrapper arena allocator for the continuation
ArenaAllocator aa = {{aa_alloc, aa_realloc, aa_free}, state->arena};
HParser *kx = be->k((HAllocator *)&aa, res->ast, be->env);
if(!kx) {
h_delete_arena(arena);
return NULL;
}
res = h_do_parse(kx, state);
h_delete_arena(arena);
return res;
return h_do_parse(kx, state);
}
static const HParserVtable bind_vt = {
@ -76,7 +70,6 @@ HParser *h_bind__m(HAllocator *mm__,
be->p = p;
be->k = k;
be->env = env;
be->mm__ = mm__;
return h_new_parser(mm__, &bind_vt, be);
}