home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 5 Edit
/
05-Edit.zip
/
me34src.zip
/
me3
/
mc
/
control.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-01-14
|
5KB
|
186 lines
/* control.c : Compile control structures like while, for next, etc.
* Return: class
*/
/* Copyright 1990, 1991, 1992 Craig Durland
* Distributed under the terms of the GNU General Public License.
* Distributed "as is", without warranties of any kind, but comments,
* suggestions and bug reports are welcome.
*/
#include <os.h>
#include "mc.h"
#include "mm.h"
#include "opcode.h"
extern char token[];
extern int
breaklabel, contlabel, /* in mc.c */
btv;
extern unsigned int class; /* in mc.c */
/* (while (test)(body))
* Compiles down to:
* 1: if (test) is FALSE goto 2 ; ignore if (test) ==TRUE
* (body)
* goto 1
* 2:
*/
comp_while()
{
int l1, ldone, savebl = breaklabel, savecl = contlabel,z;
l1 = contlabel = genlabel(); ldone = breaklabel = genlabel();
stufflabel(l1);
lookahead(); /* check for TRUE or FALSE */
if (class == BOOLEAN)
{
if (btv == FALSE) /* (while FALSE (body) */
{
groan("while loop never executed.");
gojmp(JMP,ldone);
}
get_token();
}
else /* compile (test) */
{ compile(); type_check(BOOLEAN,0); gojmp(JMPFALSE,ldone); }
compile(); z = class; /* compile (body), save result */
gojmp(JMP,l1); /* jump back to (test) */
stufflabel(ldone); /* next address after (body) */
breaklabel = savebl; contlabel = savecl;
/* If we did a (push-arg) and we are compiling args for a fcn
* call, don't push RV.
* Else we don't know what RV is because of possible
* (break)
*/
return (z == PUSHEDARGS) ? PUSHEDARGS : UNKNOWN;
}
/* (for (init)(test)(inc)(body)) : a glorified while
* Compiles down to:
* (init)
* 1: if (test) is FALSE goto 3
* (goto 2)
* (inc)
* 2: (body)
* (goto 1)
* 3:
*/
comp_for()
{
int l1, l2, savebl = breaklabel, savecl = contlabel, z;
l1 = genlabel(); contlabel = genlabel(); l2 = genlabel();
breaklabel = genlabel();
compile(); /* (init) */
stufflabel(l1); /* (test) */
compile(); type_check(BOOLEAN,0); gojmp(JMPFALSE,breaklabel);
gojmp(JMP,l2); /* jmp around (inc) */
stufflabel(contlabel); compile(); gojmp(JMP,l1); /* (inc) */
stufflabel(l2); compile(); z = class; gojmp(JMP,contlabel); /* (body) */
stufflabel(breaklabel);
breaklabel = savebl; contlabel = savecl;
return (z == PUSHEDARGS) ? PUSHEDARGS : UNKNOWN; /* same as (while) */
}
/* (if (test) (t) (f))
* Compiles down to:
* if (test) is FALSE goto 1
* (t)
* goto 2 ; not used if no else clause
* 1: (f) ; not used if no else clause
* 2: ; not used if no else clause
* Note:
* (if () ...) means use RV for the test.
*/
comp_if(lastclass) unsigned int lastclass;
{
int l1, l2, z;
l1 = genlabel();
compile(); if (class == EMPTY) class = lastclass;
type_check(BOOLEAN,0); gojmp(JMPFALSE,l1);
compile(); z = class;
lookahead(); /* check for else block */
if (class == DELIMITER && *token == ')') stufflabel(l1);
else
{
l2 = genlabel();
gojmp(JMP,l2); stufflabel(l1);
compile(); if (z != class) z = UNKNOWN;
stufflabel(l2);
}
return z;
}
/* (cond (test1) (body1) (test2) (body2) ...)
* A glorified if then else if then else if then else ...
* Compiles down to:
* if (test1) is FALSE goto 2
* (body1)
* goto done
* 2: if (test2) is FALSE goto 3
* (body2)
* goto done
* 3:
* done:
*/
comp_cond()
{
int l1, ldone;
ldone = genlabel();
do
{
l1 = genlabel();
compile(); type_check(BOOLEAN,0); gojmp(JMPFALSE,l1);
compile(); gojmp(JMP,ldone);
stufflabel(l1);
}
while (gaze_ahead(BOOLEAN,0));
stufflabel(ldone);
return UNKNOWN;
}
/* (switch val val1 (body1) val2 (body2) ... [default (dbody)])
* A simplified if then else if then else if then else
* Compiles down to:
* push val
* if val1 != val goto 2
* body1
* goto done
* 2: if val2 != val goto 3
* body2
* goto done
* 3: ...
* (dbody) ; the default case
* done: pop val
*/
comp_switch()
{
int l1, ldone, z;
ldone = genlabel();
compile(); z = class;
checkit("switch",STRING,NUMBER,BOOLEAN,0);
pushpush();
do
{
lookahead();
if (class == TOKEN && strcmp(token,"default") == 0)
{ get_token(); compile(); break; }
else
{
l1 = genlabel();
genop(DUP); compile();
if (z != UNKNOWN) type_check(z,0); /* yukk!!! */
genop(CMP); gojmp(JMPFALSE,l1);
compile(); gojmp(JMP,ldone);
stufflabel(l1);
}
} while (gaze_ahead(TOKEN,STRING,NUMBER,BOOLEAN,0));
stufflabel(ldone); genop(POP);
return UNKNOWN;
}