[INTERPRETER]
* NEW: GOSUB can be recursive now, by saving the control variables, and restoring them on RETURN. [COMPILER] * NEW: GOSUB can be used on any top-level labels. git-svn-id: svn://localhost/gambas/trunk@4534 867c0c6c-44f3-4631-809d-bfa615b0a4ec
This commit is contained in:
parent
6bd3a8a3a8
commit
8dfb763782
4 changed files with 62 additions and 32 deletions
|
@ -337,7 +337,7 @@ void TRANS_control_exit()
|
|||
|
||||
if (goto_info[i].gosub)
|
||||
{
|
||||
if (label->ctrl_id || goto_info[i].pos > label->pos)
|
||||
if (label->ctrl_id)
|
||||
THROW("Forbidden GOSUB");
|
||||
}
|
||||
else
|
||||
|
@ -1074,7 +1074,7 @@ void TRANS_catch(void)
|
|||
void TRANS_label(void)
|
||||
{
|
||||
CLASS_SYMBOL *sym;
|
||||
int sym_index, i;
|
||||
int sym_index;
|
||||
TRANS_LABEL *label;
|
||||
|
||||
sym_index = PATTERN_index(*JOB->current);
|
||||
|
@ -1101,6 +1101,7 @@ void TRANS_label(void)
|
|||
/* on saute le ':' */
|
||||
JOB->current++;
|
||||
|
||||
/*
|
||||
// A new set of control stack slots must be used for a GOSUB subroutine
|
||||
|
||||
for (i = 0; i < ARRAY_count(goto_info); i++)
|
||||
|
@ -1111,6 +1112,7 @@ void TRANS_label(void)
|
|||
return;
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -849,19 +849,29 @@ _NEW:
|
|||
|
||||
_GOSUB:
|
||||
|
||||
if (!GP)
|
||||
{
|
||||
ALLOC_ZERO(&GP, sizeof(STACK_GOSUB), "EXEC_loop");
|
||||
}
|
||||
STACK_GOSUB *gp;
|
||||
VALUE *ctrl;
|
||||
int i;
|
||||
|
||||
if (!GP)
|
||||
ARRAY_create(&GP);
|
||||
|
||||
if (GP->level == MAX_GOSUB_LEVEL)
|
||||
{
|
||||
ALLOC_ZERO(&GP->next, sizeof(STACK_GOSUB), "EXEC_loop");
|
||||
GP->next->prev = GP;
|
||||
GP = GP->next;
|
||||
gp = ARRAY_add(&GP);
|
||||
gp->pc = PC - FP->code;
|
||||
if (FP->n_ctrl)
|
||||
{
|
||||
ALLOC(&gp->ctrl, sizeof(VALUE) * FP->n_ctrl, "EXEC_loop._GOSUB");
|
||||
ctrl = &BP[FP->n_local];
|
||||
for (i = 0; i < FP->n_ctrl; i++)
|
||||
{
|
||||
gp->ctrl[i] = ctrl[i];
|
||||
ctrl[i].type = T_NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
gp->ctrl = NULL;
|
||||
}
|
||||
|
||||
GP->pc[GP->level++] = PC - FP->code;
|
||||
|
||||
/*-----------------------------------------------*/
|
||||
|
||||
|
@ -903,6 +913,9 @@ _RETURN:
|
|||
static const void *return_jump[] = { &&__RETURN_GOSUB, &&__RETURN_VALUE, &&__RETURN_VOID };
|
||||
|
||||
TYPE type;
|
||||
STACK_GOSUB *gp;
|
||||
VALUE *ctrl;
|
||||
int i, n;
|
||||
|
||||
goto *return_jump[GET_UX()];
|
||||
|
||||
|
@ -910,18 +923,29 @@ _RETURN:
|
|||
|
||||
if (!GP)
|
||||
goto __RETURN_VOID;
|
||||
|
||||
n = ARRAY_count(GP);
|
||||
if (n == 0)
|
||||
goto __RETURN_VOID;
|
||||
|
||||
if (GP->level == 0)
|
||||
gp = &GP[n - 1];
|
||||
PC = FP->code + gp->pc + 2;
|
||||
if (FP->n_ctrl)
|
||||
{
|
||||
STACK_GOSUB *prev = GP->prev;
|
||||
IFREE(GP, "EXEC_loop");
|
||||
GP = prev;
|
||||
if (!prev)
|
||||
goto __RETURN_VOID;
|
||||
ctrl = &BP[FP->n_local];
|
||||
for (i = 0; i < FP->n_ctrl; i++)
|
||||
{
|
||||
RELEASE(&ctrl[i]);
|
||||
ctrl[i] = gp->ctrl[i];
|
||||
}
|
||||
FREE(&gp->ctrl, "EXEC_loop._RETURN");
|
||||
}
|
||||
|
||||
GP->level--;
|
||||
PC = FP->code + GP->pc[GP->level] + 2;
|
||||
|
||||
if (n == 1)
|
||||
ARRAY_delete(&GP);
|
||||
else
|
||||
ARRAY_remove_last(&GP);
|
||||
|
||||
goto _MAIN;
|
||||
|
||||
__RETURN_VALUE:
|
||||
|
|
|
@ -268,12 +268,19 @@ STACK_BACKTRACE *STACK_get_backtrace(void)
|
|||
|
||||
void STACK_free_gosub_stack(STACK_GOSUB *gosub)
|
||||
{
|
||||
int i, j;
|
||||
STACK_GOSUB *p;
|
||||
|
||||
while (gosub)
|
||||
if (FP->n_ctrl)
|
||||
{
|
||||
p = gosub;
|
||||
gosub = gosub->next;
|
||||
IFREE(p, "STACK_free_gosub_stack");
|
||||
for (i = 0, p = gosub; i < ARRAY_count(gosub); i++, p++)
|
||||
{
|
||||
for (j = 0; j < FP->n_ctrl; j++)
|
||||
RELEASE(&p->ctrl[j]);
|
||||
|
||||
FREE(&p->ctrl, "STACK_free_gosub_stack");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ARRAY_delete(&gosub);
|
||||
}
|
||||
|
|
|
@ -36,16 +36,13 @@ typedef
|
|||
PACKED
|
||||
STACK_BACKTRACE;
|
||||
|
||||
#define MAX_GOSUB_LEVEL 119
|
||||
//#define MAX_GOSUB_LEVEL 119
|
||||
|
||||
typedef
|
||||
struct _STACK_GOSUB {
|
||||
ushort level;
|
||||
ushort pc[MAX_GOSUB_LEVEL];
|
||||
struct _STACK_GOSUB *next;
|
||||
struct _STACK_GOSUB *prev;
|
||||
ushort pc;
|
||||
VALUE *ctrl;
|
||||
}
|
||||
PACKED
|
||||
STACK_GOSUB;
|
||||
|
||||
typedef
|
||||
|
|
Loading…
Reference in a new issue