From 8dfb763782a673461c039e793e3b42bd5f0cc284 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Minisini?= Date: Sun, 4 Mar 2012 23:43:07 +0000 Subject: [PATCH] [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 --- main/gbc/gbc_trans_ctrl.c | 6 ++-- main/gbx/gbx_exec_loop.c | 62 +++++++++++++++++++++++++++------------ main/gbx/gbx_stack.c | 17 +++++++---- main/gbx/gbx_stack.h | 9 ++---- 4 files changed, 62 insertions(+), 32 deletions(-) diff --git a/main/gbc/gbc_trans_ctrl.c b/main/gbc/gbc_trans_ctrl.c index 0fa0a03c7..41ffa4556 100644 --- a/main/gbc/gbc_trans_ctrl.c +++ b/main/gbc/gbc_trans_ctrl.c @@ -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; } } + */ } diff --git a/main/gbx/gbx_exec_loop.c b/main/gbx/gbx_exec_loop.c index ad1da36ff..ab90add39 100644 --- a/main/gbx/gbx_exec_loop.c +++ b/main/gbx/gbx_exec_loop.c @@ -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: diff --git a/main/gbx/gbx_stack.c b/main/gbx/gbx_stack.c index 3435593c1..e47cc3ed3 100644 --- a/main/gbx/gbx_stack.c +++ b/main/gbx/gbx_stack.c @@ -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"); + } } -} \ No newline at end of file + + ARRAY_delete(&gosub); +} diff --git a/main/gbx/gbx_stack.h b/main/gbx/gbx_stack.h index 69752c2ce..e6739d19b 100644 --- a/main/gbx/gbx_stack.h +++ b/main/gbx/gbx_stack.h @@ -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