enhanced the compiler to store some jump positions in a dynamical data structure when parsing the if expresson
This commit is contained in:
parent
5c6a5f4baf
commit
e80b2bc572
119
moo/lib/comp.c
119
moo/lib/comp.c
@ -4278,6 +4278,8 @@ static int compile_basic_expression (moo_t* moo, const moo_oocs_t* ident, const
|
|||||||
|
|
||||||
static int compile_braced_block (moo_t* moo)
|
static int compile_braced_block (moo_t* moo)
|
||||||
{
|
{
|
||||||
|
/* handle a code block enclosed in { } */
|
||||||
|
|
||||||
moo_oow_t code_start;
|
moo_oow_t code_start;
|
||||||
if (TOKEN_TYPE(moo) != MOO_IOTOK_LBRACE)
|
if (TOKEN_TYPE(moo) != MOO_IOTOK_LBRACE)
|
||||||
{
|
{
|
||||||
@ -4343,83 +4345,160 @@ static int compile_conditional (moo_t* moo)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct oow_pool_chunk_t oow_pool_chunk_t;
|
||||||
|
struct oow_pool_chunk_t
|
||||||
|
{
|
||||||
|
moo_oow_t buf[16];
|
||||||
|
oow_pool_chunk_t* next;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct oow_pool_t oow_pool_t;
|
||||||
|
struct oow_pool_t
|
||||||
|
{
|
||||||
|
oow_pool_chunk_t static_chunk;
|
||||||
|
oow_pool_chunk_t* head;
|
||||||
|
oow_pool_chunk_t* tail;
|
||||||
|
moo_oow_t count;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void init_oow_pool (moo_t* moo, oow_pool_t* pool)
|
||||||
|
{
|
||||||
|
pool->count = 0;
|
||||||
|
pool->static_chunk.next = MOO_NULL;
|
||||||
|
pool->head = &pool->static_chunk;
|
||||||
|
pool->tail = &pool->static_chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fini_oow_pool (moo_t* moo, oow_pool_t* pool)
|
||||||
|
{
|
||||||
|
oow_pool_chunk_t* chunk, * next;
|
||||||
|
|
||||||
|
/* dispose all chunks except the first static one */
|
||||||
|
chunk = pool->head->next;
|
||||||
|
while (chunk)
|
||||||
|
{
|
||||||
|
next = chunk->next;
|
||||||
|
moo_freemem (moo, chunk);
|
||||||
|
chunk = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* this doesn't reinitialize the pool. call init_oow_pool()
|
||||||
|
* to reuse it */
|
||||||
|
}
|
||||||
|
|
||||||
|
static int add_to_oow_pool (moo_t* moo, oow_pool_t* pool, moo_oow_t v)
|
||||||
|
{
|
||||||
|
moo_oow_t idx;
|
||||||
|
|
||||||
|
idx = pool->count % MOO_COUNTOF(pool->static_chunk.buf);
|
||||||
|
if (pool->count > 0 && idx == 0)
|
||||||
|
{
|
||||||
|
oow_pool_chunk_t* chunk;
|
||||||
|
|
||||||
|
chunk = moo_allocmem (moo, MOO_SIZEOF(pool->static_chunk));
|
||||||
|
if (!chunk) return -1;
|
||||||
|
|
||||||
|
chunk->next = MOO_NULL;
|
||||||
|
pool->tail->next = chunk;
|
||||||
|
pool->tail = chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
pool->tail->buf[idx] = v;
|
||||||
|
pool->count++;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int compile_if_expression (moo_t* moo)
|
static int compile_if_expression (moo_t* moo)
|
||||||
{
|
{
|
||||||
moo_oow_t jumptoend[100];
|
oow_pool_t jumptoend;
|
||||||
moo_oow_t jumptoend_count = 0;
|
oow_pool_chunk_t* jumptoend_chunk;
|
||||||
|
moo_oow_t i, j;
|
||||||
|
|
||||||
moo_oow_t i;
|
|
||||||
moo_oow_t jumptonext;
|
moo_oow_t jumptonext;
|
||||||
moo_ioloc_t if_loc, brace_loc;
|
moo_ioloc_t if_loc, brace_loc;
|
||||||
|
|
||||||
MOO_ASSERT (moo, TOKEN_TYPE(moo) == MOO_IOTOK_IF);
|
MOO_ASSERT (moo, TOKEN_TYPE(moo) == MOO_IOTOK_IF);
|
||||||
if_loc = *TOKEN_LOC(moo);
|
if_loc = *TOKEN_LOC(moo);
|
||||||
|
|
||||||
|
init_oow_pool (moo, &jumptoend);
|
||||||
|
|
||||||
/* TODO: simple optimization to check if the conditional is true or false */
|
/* TODO: simple optimization to check if the conditional is true or false */
|
||||||
GET_TOKEN (moo); /* get ( */
|
GET_TOKEN (moo); /* get ( */
|
||||||
if (compile_conditional (moo) <= -1) return -1;
|
if (compile_conditional (moo) <= -1) goto oops;
|
||||||
|
|
||||||
/* insert dummy instructions before replacing them with a jump instruction */
|
|
||||||
jumptonext = moo->c->mth.code.len;
|
jumptonext = moo->c->mth.code.len;
|
||||||
/* specifying MAX_CODE_JUMP causes emit_single_param_instruction() to
|
/* specifying MAX_CODE_JUMP causes emit_single_param_instruction() to
|
||||||
* produce the long jump instruction (BCODE_JUMP_FORWARD_X) */
|
* produce the long jump instruction (BCODE_JUMP_FORWARD_X) */
|
||||||
if (emit_single_param_instruction (moo, BCODE_JUMP_FORWARD_IF_FALSE_0, MAX_CODE_JUMP) <= -1) return -1;
|
if (emit_single_param_instruction (moo, BCODE_JUMP_FORWARD_IF_FALSE_0, MAX_CODE_JUMP) <= -1) goto oops;
|
||||||
|
|
||||||
GET_TOKEN (moo); /* get { */
|
GET_TOKEN (moo); /* get { */
|
||||||
brace_loc = *TOKEN_LOC(moo);
|
brace_loc = *TOKEN_LOC(moo);
|
||||||
if (compile_braced_block (moo) <= -1) return -1;
|
if (compile_braced_block (moo) <= -1) goto oops;
|
||||||
|
|
||||||
/* emit code to jump to the end */
|
/* emit code to jump to the end */
|
||||||
jumptoend[jumptoend_count++] = moo->c->mth.code.len;
|
/*jumptoend[jumptoend_count++] = moo->c->mth.code.len;*/
|
||||||
if (emit_single_param_instruction (moo, BCODE_JUMP_FORWARD_0, MAX_CODE_JUMP) <= -1) return -1;
|
if (add_to_oow_pool(moo, &jumptoend, moo->c->mth.code.len) <= -1) goto oops;
|
||||||
|
if (emit_single_param_instruction (moo, BCODE_JUMP_FORWARD_0, MAX_CODE_JUMP) <= -1) goto oops;
|
||||||
|
|
||||||
GET_TOKEN (moo);
|
GET_TOKEN (moo);
|
||||||
while (TOKEN_TYPE(moo) == MOO_IOTOK_ELSIF)
|
while (TOKEN_TYPE(moo) == MOO_IOTOK_ELSIF)
|
||||||
{
|
{
|
||||||
if (patch_jump_instruction (moo, jumptonext, BCODE_JUMP2_FORWARD_IF_FALSE, &brace_loc) <= -1) return -1;
|
if (patch_jump_instruction (moo, jumptonext, BCODE_JUMP2_FORWARD_IF_FALSE, &brace_loc) <= -1) goto oops;
|
||||||
|
|
||||||
GET_TOKEN (moo); /* get ( */
|
GET_TOKEN (moo); /* get ( */
|
||||||
if (compile_conditional(moo) <= -1) return -1;
|
if (compile_conditional(moo) <= -1) goto oops;
|
||||||
|
|
||||||
/* emit code to jump to the next elsif or else */
|
/* emit code to jump to the next elsif or else */
|
||||||
jumptonext = moo->c->mth.code.len;
|
jumptonext = moo->c->mth.code.len;
|
||||||
if (emit_single_param_instruction (moo, BCODE_JUMP_FORWARD_IF_FALSE_0, MAX_CODE_JUMP) <= -1) return -1;
|
if (emit_single_param_instruction (moo, BCODE_JUMP_FORWARD_IF_FALSE_0, MAX_CODE_JUMP) <= -1) goto oops;
|
||||||
|
|
||||||
GET_TOKEN (moo); /* get { */
|
GET_TOKEN (moo); /* get { */
|
||||||
brace_loc = *TOKEN_LOC(moo);
|
brace_loc = *TOKEN_LOC(moo);
|
||||||
if (compile_braced_block(moo) <= -1) return -1;
|
if (compile_braced_block(moo) <= -1) goto oops;
|
||||||
|
|
||||||
/* emit code to jump to the end */
|
/* emit code to jump to the end */
|
||||||
jumptoend[jumptoend_count++] = moo->c->mth.code.len;
|
/*jumptoend[jumptoend_count++] = moo->c->mth.code.len;*/
|
||||||
if (emit_single_param_instruction (moo, BCODE_JUMP_FORWARD_0, MAX_CODE_JUMP) <= -1) return -1;
|
if (add_to_oow_pool(moo, &jumptoend, moo->c->mth.code.len) <= -1) goto oops;
|
||||||
|
if (emit_single_param_instruction (moo, BCODE_JUMP_FORWARD_0, MAX_CODE_JUMP) <= -1) goto oops;
|
||||||
|
|
||||||
GET_TOKEN (moo); /* get the next token after } */
|
GET_TOKEN (moo); /* get the next token after } */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (patch_jump_instruction (moo, jumptonext, BCODE_JUMP2_FORWARD_IF_FALSE, &brace_loc) <= -1) return -1;
|
if (patch_jump_instruction (moo, jumptonext, BCODE_JUMP2_FORWARD_IF_FALSE, &brace_loc) <= -1) goto oops;
|
||||||
|
|
||||||
if (TOKEN_TYPE(moo) == MOO_IOTOK_ELSE)
|
if (TOKEN_TYPE(moo) == MOO_IOTOK_ELSE)
|
||||||
{
|
{
|
||||||
GET_TOKEN (moo); /* get { */
|
GET_TOKEN (moo); /* get { */
|
||||||
if (compile_braced_block (moo) <= -1) return -1;
|
if (compile_braced_block (moo) <= -1) goto oops;
|
||||||
GET_TOKEN (moo); /* get the next token after } */
|
GET_TOKEN (moo); /* get the next token after } */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* emit code to push nil if no 'else' part exists */
|
/* emit code to push nil if no 'else' part exists */
|
||||||
if (emit_byte_instruction (moo, BCODE_PUSH_NIL) <= -1) return -1;
|
if (emit_byte_instruction (moo, BCODE_PUSH_NIL) <= -1) goto oops;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* patch instructions that jumps to the end of if expression */
|
/* patch instructions that jumps to the end of if expression */
|
||||||
for (i = 0; i < jumptoend_count; i++)
|
for (jumptoend_chunk = jumptoend.head, i = 0; jumptoend_chunk; jumptoend_chunk = jumptoend_chunk->next)
|
||||||
{
|
{
|
||||||
/* pass if_loc to every call to patch_jump_instruction().
|
/* pass if_loc to every call to patch_jump_instruction().
|
||||||
* it's harmless because if the first call doesn't flood, the subseqent
|
* it's harmless because if the first call doesn't flood, the subseqent
|
||||||
* call will never flood either. */
|
* call will never flood either. */
|
||||||
if (patch_jump_instruction (moo, jumptoend[i], BCODE_JUMP2_FORWARD_IF_FALSE, &if_loc) <= -1) return -1;
|
for (j = 0; j < MOO_COUNTOF(jumptoend.static_chunk.buf) && i < jumptoend.count; j++)
|
||||||
|
{
|
||||||
|
if (patch_jump_instruction (moo, jumptoend_chunk->buf[j], BCODE_JUMP2_FORWARD_IF_FALSE, &if_loc) <= -1) goto oops;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fini_oow_pool (moo, &jumptoend);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
oops:
|
||||||
|
fini_oow_pool (moo, &jumptoend);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int compile_method_expression (moo_t* moo, int pop)
|
static int compile_method_expression (moo_t* moo, int pop)
|
||||||
|
Loading…
Reference in New Issue
Block a user