/*
This file is part of the FElt finite element analysis package.
Copyright (C) 1993-2000 Jason I. Gobat and Darren C. Atkinson
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/************************************************************************
* File: loop.c *
* *
* Description: This file contains the public and private function and *
* type definitions for translating loop constructs during *
* parsing. *
************************************************************************/
# include "loop.h"
# include "error.h"
# include "lexer.h"
# include "codegen.h"
# include "allocate.h"
# include "descriptor.h"
# include "tokens.h"
struct break_node {
break_node link;
Address addr;
int type;
};
struct loop_node {
loop_node link;
break_node queue;
int type;
};
static loop_node loop_stack;
/************************************************************************
* Function: start_break *
* *
* Description: Starts a break or next expression by removing the top *
* entry of the loop stack and popping the generator state *
* if necessary. *
************************************************************************/
loop_node start_break (type)
int type;
{
loop_node node;
if ((node = loop_stack)) {
loop_stack = node -> link;
if (type == BREAK && node -> type == FOR)
emit (PopOp, 3);
} else if (type == BREAK)
cterror ("break expression not within a loop");
else
cterror ("next expression not within a loop");
return node;
}
/************************************************************************
* Function: end_break *
* *
* Description: Ends a break or next expression by restoring the top of *
* the loop stack, adding the expression to the queue for *
* the current depth, and emitting a jump instruction. *
************************************************************************/
void end_break (type, lnode)
int type;
loop_node lnode;
{
break_node bnode;
if (lnode) {
loop_stack = lnode;
bnode = New (struct break_node);
bnode -> link = lnode -> queue;
bnode -> type = type;
bnode -> addr = ip;
lnode -> queue = bnode;
emit (JmpOp, 0);
}
}
/************************************************************************
* Function: enter_loop *
* *
* Description: Enters a while or for loop by adding a new entry to the *
* loop stack. *
************************************************************************/
void enter_loop (type)
int type;
{
loop_node node;
node = New (struct loop_node);
node -> type = type;
node -> queue = NULL;
node -> link = loop_stack;
loop_stack = node;
}
/************************************************************************
* Function: exit_loop *
* *
* Description: Exits a while or for loop by removing the top entry of *
* the loop stack and processing any break or next *
* expressions on its queue. *
************************************************************************/
void exit_loop (start, end)
Address start;
Address end;
{
loop_node lnode;
break_node bnode;
break_node next;
if ((lnode = loop_stack)) {
loop_stack = lnode -> link;
for (bnode = lnode -> queue; bnode; bnode = next) {
patch (bnode -> addr, JmpOp, bnode -> type == BREAK ? end : start);
next = bnode -> link;
Delete (bnode);
}
Delete (lnode);
}
}
/************************************************************************
* Function: exit_all *
* *
* Description: Exits all loops by repeatedly popping the loop stack *
* and destroying the queues. *
************************************************************************/
void exit_all ( )
{
loop_node lnode;
break_node bnode;
loop_node next_lnode;
break_node next_bnode;
for (lnode = loop_stack; lnode; lnode = next_lnode) {
for (bnode = lnode -> queue; bnode; bnode = next_bnode) {
next_bnode = bnode -> link;
Delete (bnode);
}
next_lnode = lnode -> link;
Delete (lnode);
}
}
syntax highlighted by Code2HTML, v. 0.9.1