home services resume portfolio contact us about me


Return To Portfolio Home


/* ----------------------------------------------------------------------
 * FILE: rhcompile.c
 * PACKAGE: rh - recursive file finder.
 * VERSION: 4.0
 * DESCRIPTION:
 *	Contains functions that compile byte-code from a rh source file.
 *
 * REVISION HISTORY:
 *	Oct. 27. 1990 - Created.
 *
 * AUTHOR:
 *	Ken Stauffer.
 * ---------------------------------------------------------------------- */

#include "rh.h"
#include "rhparse.h"

struct object		*Program;
static int		Progsize;
static int		LC;	/* location counter */

int		beginLC = -1;
int		endLC = -1;
int		startLC = -1;
static int	LC1 = -1;
static int	LC2 = -1;

char			*malloc(), *realloc();
extern int		lineno;
extern struct builtin	builtins[];
extern char		*rhfilename;

extern char		StringStack[];
extern char		*sfree;
extern char		*mkstr();
extern int		rmstr();

comp_num(opcode,operand,type)
short opcode;
long operand;
short type;
{
	if( LC >= Progsize ) {
		Progsize += PROG_GROW;
		Program  = (struct object *) realloc(Program,
					Progsize*sizeof(struct object));
		if( Program == NULL )
			error("out of memory");
	}
	Program[ LC ].opcode = opcode;
	Program[ LC ].type = type;
	Program[ LC ].val = operand;
	LC++;
}

comp_str(opcode,operand,type)
short opcode;
char *operand;
short type;
{
	if( LC >= Progsize ) {
		Progsize += PROG_GROW;
		Program  = (struct object *) realloc(Program,
					Progsize*sizeof(struct object));
		if( Program == NULL )
			error("out of memory");
	}
	Program[ LC ].opcode = opcode;
	Program[ LC ].type = type;
	Program[ LC ].str = operand;
	LC++;
}

comp_obj(opcode,operand,type)
short opcode;
struct object *operand;
short type;
{
	if( LC >= Progsize ) {
		Progsize += PROG_GROW;
		Program  = (struct object *) realloc(Program,
					Progsize*sizeof(struct object));
		if( Program == NULL )
			error("out of memory");
	}
	Program[ LC ].opcode = opcode;
	Program[ LC ].type = type;
	Program[ LC ].obj = operand;
	LC++;
}

struct expr *genstring(s)
char *s;
{
	struct expr *e;
	e = (struct expr *) malloc( sizeof(struct expr) );
	if( e == NULL )
		error("out of memory");
	e->opcode = OP_STRING;
	e->str = s;
	e->left = e->right = NULL;
	return e;
}

struct expr *gennumber(v)
long v;
{
	struct expr *e;
	e = (struct expr *) malloc( sizeof(struct expr) );
	if( e == NULL )
		error("out of memory");
	e->opcode = OP_NUMBER;
	e->val = v;
	e->left = e->right = NULL;
	return e;
}

struct expr *genvar(sym,expr)
struct symbol *sym;
struct expr *expr;
{
	struct expr *e;

	e = (struct expr *) malloc( sizeof(struct expr) );
	if( e == NULL )
		error("out of memory");

	if( expr == NULL ) {
		e->opcode = OP_VAR;
		e->obj = sym->obj;
		e->left = e->right = NULL;
	} else {
		e->opcode = OP_AVAR;
		e->obj = sym->obj;
		e->left = NULL;
		e->right = expr;
	}
	return e;
}

struct expr *genident(sym,expr)
struct symbol *sym;
struct expr *expr;
{
	struct object *o;

	/* check to see if 'sym' is still an identifier,
	 * because it is possible that another portion of the
	 * parse consisted of another instance of this IDENTIFIER.
	 *	eg. (foo + foo / foo)
	 */
	if( sym->type == IDENTIFIER ) {
		o = (struct object *) malloc( sizeof(struct object) );
		if( o == NULL )
			error("out of memory");

		o->type = T_NONE;
		o->opcode = 0;
		o->obj = NULL;
		sym->type = VARIABLE;
		sym->obj = o;
		sym->bvar = 0;
	}

	return genvar(sym,expr);
}

struct expr *genparam(sym,expr)
struct symbol *sym;
struct expr *expr;
{
	struct expr *e;

	e = (struct expr *) malloc( sizeof(struct expr) );
	if( e == NULL )
		error("out of memory");

	if( expr == NULL ) {
		e->opcode = OP_PARAM;
		e->val = sym->val;
		e->left = e->right = NULL;
	} else {
		e->opcode = OP_APARAM;
		e->val = sym->val;
		e->left = NULL;
		e->right = expr;
	}
	return e;
}

struct expr *genargs(args,expr)
struct expr *args,*expr;
{
	struct expr *e;
	e = (struct expr *) malloc( sizeof(struct expr) );
	if( e == NULL )
		error("out of memory");

	e->opcode = 0;
	if( args == NULL )
		e->val = 0;
	else
		e->val = args->val + 1;
	e->left = expr;
	e->right = args;
	return e;
}

struct expr *genfunc(func,args)
struct symbol *func;
struct expr *args;
{
	struct expr *e;
	int argcount;

	if( args == NULL )
		argcount = 0;
	else
		argcount = args->val+1;

	if( argcount > func->val )
		error("too many arguments to function %s",func->name);
	else if( argcount < func->val )
		error("not enough arguments to function %s",func->name);

	e = (struct expr *) malloc( sizeof(struct expr) );
	if( e == NULL )
		error("out of memory");

	e->opcode = OP_CALL;
	e->type = lineno;
	e->val = func->pctr;
	e->left = NULL;
	e->right = args;
	return e;
}

struct expr *genbuiltin(builtin,args)
struct symbol *builtin;
struct expr *args;
{
	struct expr *e;

	e = (struct expr *) malloc( sizeof(struct expr) );
	if( e == NULL )
		error("out of memory");

	e->opcode = OP_BUILTIN;
	e->str = builtin->name;
	e->left = NULL;
	e->right = args;
	return e;
}

struct expr *genbinary(opcode,e1,e2)
struct expr *e1,*e2;
int opcode;
{
	struct expr *e;

	e = (struct expr *) malloc( sizeof(struct expr) );
	if( e == NULL )
		error("out of memory");

	e->opcode = opcode;
	e->left = e1;
	e->right = e2;
	return e;
}

struct expr *gentrinary(e1,e2,e3)
struct expr *e1,*e2,*e3;
{
	struct expr *n1, *n2;

	n2 = (struct expr *) malloc( sizeof(struct expr) );
	if( e2 == NULL )
		error("out of memory");

	n2->opcode = 0;
	n2->left = e2;
	n2->right = e3;

	n1 = (struct expr *) malloc( sizeof(struct expr) );
	if( n1 == NULL )
		error("out of memory");

	n1->opcode = OP_IFFALSE;
	n1->left = e1;
	n1->right = n2;

	return n1;
}

func_1(func,args)
struct symbol *func, *args;
{
	func->type = FUNCTION;
	func->pctr = LC;
	func->val = (args) ? args->val+1 : 0;
}

func_2(func,args)
struct symbol *func, *args;
{
	struct symbol *p, *q;
	int i;

	func->param = NULL;
	comp_num(OP_RET,func->val,0);
	p = args;
	while(p) {
		q = p->param;
		remove(p->name);
		p = q;
	}

	for(i=func->pctr; i<LC; i++) {
		if(Program[i].opcode == OP_GOTO && Program[i].type == BREAK ) {
			lineno = Program[i].val;
			error("illegal context for BREAK statement");
		}
		if(Program[i].opcode == OP_GOTO &&
					Program[i].type == CONTINUE ) {
			lineno = Program[i].val;
			error("illegal context for CONTINUE statement");
		}
	}
}

genbeg1()
{
	if( beginLC >= 0 )
		error("BEGIN action already defined");
	beginLC = LC;
}

genbeg2()
{
	comp_num(OP_END,0,0);
}

genend1()
{
	if( endLC >= 0 )
		error("END action already defined");
	endLC = LC;
}

genend2()
{
	comp_num(OP_END,0,0);
}

gen1match(e)
struct expr *e;
{
	if( startLC < 0 )
		startLC = LC;

	if( LC1 >= 0 )
		Program[ LC1 ].val = LC;

	if( LC2 >= 0 )
		Program[ LC2 ].val = LC;

	if( e ) {
		gencode(e,T_NONE);
		LC1 = LC;

		if( e->type == T_NONE )
			comp_num(OP_IFFALSE,0,0);
		else if( e->type == T_STRING )
			comp_num(OP_IFS_FALSE,0,0);
		else if( e->type == T_NUMBER )
			comp_num(OP_IFN_FALSE,0,0);
		free(e);
	} else
		LC1 = -1;
}

gen2match()
{
	LC2 = LC;
	comp_num(OP_GOTO,0,0);
}

gendefault()
{
	struct symbol *f, *lookup();

	f = lookup("ACTION");
	if( f == NULL )
		error("no function ACTION() has been defined");
	comp_num(OP_CALL,f->pctr,0);
	comp_str(OP_POP,rhfilename,lineno);

	LC2 = LC;
	comp_num(OP_GOTO,0,0);
}

comp_builtin(expr,type)
struct expr *expr;
{
	struct object stack[30];
	struct symbol *s, *lookup();
	int fold = 1;
	int sp=0, ac;
	struct expr *e, *a;
	char *err, *dobuiltin(), *allocstr();

	s = lookup(expr->str);

	ac = (expr->right) ? expr->right->val+1 : 0;

	if( ac != s->nargs && s->nargs >= 0)
		error("incorrect number of arguments to %s()",s->name);

	if( s->rtype & T_FOLD ) {
		sfree = StringStack;
		a = expr->right;
		while(a) {
			e = a->left;
			if(e->opcode == OP_NUMBER) {
				stack[sp].type = T_NUMBER;
				stack[sp++].val = e->val;
			} else if(e->opcode == OP_STRING) {
				stack[sp].type = T_STRING;
				stack[sp++].str = mkstr(e->str);
				if(stack[sp-1].str == NULL)
					error("out of memory");
			} else {
				fold = 0; break;
			}
			a = a->right;
		}
		if( fold && !dobuiltin(s->val,stack,&sp,ac,1) ) {
			if( stack[0].type == T_NUMBER ) {
				expr->type = T_NUMBER;
				expr->val = stack[0].val;
				comp_num(OP_NUMBER,stack[0].val,0);
			} else {
				rmstr(stack[0].str);
				expr->type = T_STRING;
				expr->str = allocstr(stack[0].str);
				if( expr->str == NULL )
					error("out of memory");
				comp_str(OP_STRING,expr->str,0);
			}
			a = expr->right;
			while(a) {
				free(a->left);
				e = a->right;
				free(a);
				a = e;
			}
			return;
		}
	}
	a = expr->right;
	while(a) {
		gencode(a->left,T_NONE);
		free(a->left);
		e = a->right;
		free(a);
		a = e;
	}
	expr->type = s->rtype & ~T_FOLD;
	comp_num(OP_BUILTIN,s->val,ac);
	if( expr->type == T_NONE && type != T_NONE ) {
		comp_num(OP_CHKTYPE,type,lineno);
		expr->type = type;
	} else if( expr->type != T_NONE && type != T_NONE &&
						type != expr->type )
		error("%s() returns wrong type to be used in this context",
							s->name);
}

gen_expr(expr)
struct expr *expr;
{
	gencode(expr,T_NONE);
	free(expr);
	comp_str(OP_POP,rhfilename,lineno);
}

gen_if1(expr)
struct expr *expr;
{
	int lc;

	gencode(expr,T_NONE);
	lc = LC;
	if( expr->type == T_NONE )
		comp_num(OP_IFFALSE,0,0);
	else if( expr->type == T_NUMBER )
		comp_num(OP_IFN_FALSE,0,0);
	else if( expr->type == T_STRING )
		comp_num(OP_IFS_FALSE,0,0);
	free(expr);
	return(lc);	
}

gen_if2(lc1,lc2)
{
	if( lc2 < 0 )
		Program[ lc1 ].val = LC;
	else {
		Program[ lc1 ].val = lc2+1;
		Program[ lc2 ].val = LC;
	}
}

gen_if3()
{
	comp_num(OP_GOTO,0,0);
	return LC-1;
}

gen1while(expr)
struct expr *expr;
{
	int lc;

	lc = LC;
	gencode(expr,T_NONE);
	if( expr->type == T_NONE)
		comp_num(OP_IFFALSE,0,BREAK);
	else if( expr->type == T_NUMBER)
		comp_num(OP_IFN_FALSE,0,BREAK);
	else if( expr->type == T_STRING)
		comp_num(OP_IFS_FALSE,0,BREAK);
	free(expr);
	return lc;
}

gen2while(lc)
{
	comp_num(OP_GOTO,0,CONTINUE);
	backpatch(lc,LC-1,LC,lc);
}

gen_do1()
{
	return LC;
}

gen_do2(expr,lc)
struct expr *expr;
{
	int lc1;

	lc1 = LC;
	gencode(expr,T_NONE);
	if( expr->type == T_NONE )
		comp_num(OP_IFTRUE,lc,0);
	else if( expr->type == T_NUMBER )
		comp_num(OP_IFN_TRUE,lc,0);
	else if( expr->type == T_STRING )
		comp_num(OP_IFS_TRUE,lc,0);

	backpatch(lc,LC-1,LC,lc1);
	free(expr);
}

gen1for(expr1,expr2)
struct expr *expr1, *expr2;
{
	int lc;

	gencode(expr1,T_NONE);
	comp_str(OP_POP,rhfilename,lineno);
	free(expr1);

	lc = LC;
	gencode(expr2,T_NONE);
	if( expr2->type == T_NONE )
		comp_num(OP_IFFALSE,0,BREAK);
	else if( expr2->type == T_NUMBER )
		comp_num(OP_IFN_FALSE,0,BREAK);
	else if( expr2->type == T_STRING )
		comp_num(OP_IFS_FALSE,0,BREAK);
	free(expr2);

	return lc;
}

gen2for(lc,expr3)
struct expr *expr3;
{
	int lc1;

	lc1 = LC;
	gencode(expr3,T_NONE);
	comp_str(OP_POP,rhfilename,lineno);
	free(expr3);
	comp_num(OP_GOTO,lc,0);
	backpatch(lc,LC-1,LC,lc1);
}

/* backpatch -
 *	Looks at each element Program[from] .. Program[to]
 *	and changes FLOW CONTROL instructions of type BREAK
 *	to goto the blabel, and instructions of type CONTINUE
 *	to goto the clabel.
 */
backpatch(from,to,blabel,clabel)
{
	int i;

	for(i=from; i<= to; i++) {
		switch( Program[i].opcode ) {
		case OP_GOTO:
		case OP_IFTRUE:
		case OP_IFFALSE:
		case OP_IFS_TRUE:
		case OP_IFS_FALSE:
		case OP_IFN_FALSE:
		case OP_IFN_TRUE:
			if( Program[i].type == BREAK ) {
				Program[i].val = blabel;
				Program[i].type = 0;
			} else if( Program[i].type == CONTINUE ) {
				Program[i].val = clabel;
				Program[i].type = 0;
			}
			break;
		}
	}
}

gen_return(expr,func)
struct expr *expr;
struct symbol *func;
{
	if( func == NULL )
		error("illegal context for RETURN statement");
	gencode(expr,T_NONE);
	free(expr);
	comp_num(OP_RET,func->val,1);
}

gen_break(l)
{
	comp_num(OP_GOTO,l,BREAK);
}

gen_continue(l)
{
	comp_num(OP_GOTO,l,CONTINUE);
}

gen_next(f)
struct symbol *f;
{
	if( f )
		error("illegal context for NEXT statement");
	comp_num(OP_END,0,0);
}

char *operator(opcode)
{
	switch(opcode){
	case OP_NOT:	return("!");
	case OP_NEG:	return("-");
	case OP_BNOT:	return("~");
	case OP_MUL:	return("*");
	case OP_DIV:	return("/");
	case OP_MOD:	return("%");
	case OP_ADD:	return("+");
	case OP_SUB:	return("-");
	case OP_BOR:	return("|");
	case OP_XOR:	return("^");
	case OP_BAND:	return("&");
	case OP_GT:	return(">");
	case OP_GE:	return(">=");
	case OP_LT:	return("<");
	case OP_LE:	return("<=");
	case OP_SHL:	return("<<");
	case OP_SHR:	return(">>");
	case OP_ADDOP:	return("+=");
	case OP_SUBOP:	return("-=");
	case OP_MULOP:	return("*=");
	case OP_DIVOP:	return("/=");
	case OP_MODOP:	return("%=");
	case OP_OROP:	return("|=");
	case OP_ANDOP:	return("&=");
	case OP_LSHOP:	return("<<=");
	case OP_RSHOP:	return(">>=");
	case OP_XOROP:	return("^=");
	default:
		error("internal error in operator()");
	}
}

relational(expr,op,opnum,opstr,opname)
struct expr *expr;
char *opname;
{
	gencode(expr->left,T_NONE);
	gencode(expr->right,T_NONE);
	
	if( expr->left->type == T_NONE || expr->right->type == T_NONE )
		comp_num(op,0,0);
	else
	if( expr->left->type & T_NUMBER && expr->right->type & T_NUMBER )
		comp_num(opnum,0,0);
	else
	if( expr->left->type & T_STRING && expr->right->type & T_STRING )
		comp_num(opstr,0,0);
	else
		error("operand of %s must have the same type", opname);

	expr->type = T_NUMBER;
	free(expr->left);
	free(expr->right);
}


/* gencode -
 *	Traverse an expression tree and generate code.
 */
gencode(expr,type)
struct expr *expr;
{
	int lc1,lc2, i;
	struct expr *e, *tmp;

	switch( expr->opcode ) {
	case OP_END:
		break;

	case OP_NOT:
	case OP_NEG:
	case OP_BNOT:
		gencode(expr->right,T_NUMBER);
		if( expr->right->type != T_NUMBER )
			error("operand of %s must be an integer",
						operator(expr->opcode) );

		comp_num(expr->opcode,0,0);
		free(expr->right);
		expr->type = T_NUMBER;
		break;

	case OP_MUL:
	case OP_DIV:
	case OP_MOD:
	case OP_ADD:
	case OP_SUB:
	case OP_BOR:
	case OP_XOR:
	case OP_BAND:
	case OP_SHL:
	case OP_SHR:
		gencode(expr->left,T_NUMBER);
		gencode(expr->right,T_NUMBER);
		if( expr->left->type != T_NUMBER ||
					expr->right->type != T_NUMBER )
			error("operands of %s must be integers",
						operator(expr->opcode) );

		comp_num(expr->opcode,0,0);
		expr->type = T_NUMBER;
		free(expr->left);
		free(expr->right);
		break;

	case OP_EQ:	relational(expr,OP_EQ,OP_NUMEQ,OP_STREQ,"=="); break;
	case OP_NE:	relational(expr,OP_NE,OP_NUMNE,OP_STRNE,"!="); break;
	case OP_GT:	relational(expr,OP_GT,OP_NUMGT,OP_STRGT,">"); break;
	case OP_GE:	relational(expr,OP_GE,OP_NUMGE,OP_STRGE,">="); break;
	case OP_LT:	relational(expr,OP_LT,OP_NUMLT,OP_STRLT,"<"); break;
	case OP_LE:	relational(expr,OP_LE,OP_NUMLE,OP_STRLE,"<="); break;

	case OP_AND1:
		gencode(expr->left,T_NONE);
		lc1 = LC;

		if( expr->left->type == T_NONE )
			comp_num(OP_AND1,0,0);
		else if( expr->left->type == T_NUMBER )
			comp_num(OP_A1_NUM,0,0);
		else if( expr->left->type == T_STRING )
			comp_num(OP_A1_STR,0,0);

		gencode(expr->right,T_NONE);

		if( expr->right->type == T_NONE )
			comp_num(OP_AND2,0,0);
		else if( expr->right->type == T_NUMBER )
			comp_num(OP_A2_NUM,0,0);
		else if( expr->right->type == T_STRING )
			comp_num(OP_A2_STR,0,0);

		Program[ lc1 ].val = LC;

		free(expr->left);
		free(expr->right);
		expr->type = T_NUMBER;
		break;

	case OP_AND2:
		error("internal error in gencode()");

	case OP_OR1:
		gencode(expr->left,T_NONE);
		lc1 = LC;

		if( expr->left->type == T_NONE )
			comp_num(OP_OR1,0,0);
		else if( expr->left->type == T_NUMBER )
			comp_num(OP_OR1_NUM,0,0);
		else if( expr->left->type == T_STRING )
			comp_num(OP_OR1_STR,0,0);

		gencode(expr->right,T_NONE);

		if( expr->right->type == T_NONE )
			comp_num(OP_OR2,0,0);
		else if( expr->right->type == T_NUMBER )
			comp_num(OP_OR2_NUM,0,0);
		else if( expr->right->type == T_STRING )
			comp_num(OP_OR2_STR,0,0);

		Program[ lc1 ].val = LC;

		free(expr->left);
		free(expr->right);
		expr->type = T_NUMBER;
		break;

	case OP_OR2:
		error("internal error in gencode()");

	case OP_ASSIGN:
		gencode(expr->right,T_NONE);
		gencode(expr->left,T_LVAL);

		if( expr->right->type == T_NONE ) {
			comp_num(OP_ASSIGN,0,0);
			expr->type = T_NONE;
		} else if( expr->right->type == T_NUMBER ) {
			comp_num(OP_ASS_NUM,0,0);
			expr->type = T_NUMBER;
		} else if( expr->right->type == T_STRING ) {
			comp_num(OP_ASS_STR,0,0);
			expr->type = T_STRING;
		}
		free(expr->right);
		free(expr->left);
		break;

	case OP_PLUSPLUS:
	case OP_MINUSMINUS:
		gencode(expr->right,T_LVAL);
		free(expr->right);
		comp_num(expr->opcode,0,0);
		expr->type = T_NUMBER;
		break;

	case OP_ADDOP:
	case OP_SUBOP:
	case OP_MULOP:
	case OP_DIVOP:
	case OP_MODOP:
	case OP_OROP:
	case OP_ANDOP:
	case OP_LSHOP:
	case OP_RSHOP:
	case OP_XOROP:
		gencode(expr->right,T_NUMBER);
		if( !(expr->right->type & T_NUMBER) )
			error("rhs operand of %s must be an integer",
					operator(expr->opcode));

		gencode(expr->left,T_LVAL);
		comp_num(expr->opcode,0,0);
		expr->type = T_NUMBER;
		free(expr->right);
		free(expr->left);
		break;

	case OP_BUILTIN:
		comp_builtin(expr,type);
		break;

	case OP_CALL:
		e = expr->right;
		i = (expr->right) ? expr->right->val + 1 : 0;
		while(e) {
			gencode(e->left,T_NONE);
			free(e->left);
			tmp = e;
			e = e->right;
			free(tmp);
		}
		comp_num(OP_CALL,expr->val,i);
		if( type != T_NONE )
			comp_num(OP_CHKTYPE,expr->type,type);
		expr->type = type;
		break;

	case OP_RET:
		error("internal error in gencode()");

	case OP_GOTO:
		error("internal error in gencode()");

	case OP_NUMBER:
		comp_num(OP_NUMBER,expr->val,0);
		expr->type = T_NUMBER;
		break;

	case OP_STRING:
		comp_str(OP_STRING,expr->str,0);
		expr->type = T_STRING;
		break;

	case OP_VAR:
		comp_obj(OP_VAR,expr->obj,type);
		expr->type = type;
		break;

	case OP_AVAR:
		gencode(expr->right,T_NONE);
		comp_obj(OP_AVAR,expr->obj,type);
		expr->type = type;
		break;

	case OP_PARAM:
		comp_num(OP_PARAM,expr->val,type);
		expr->type = type;
		break;

	case OP_APARAM:
		gencode(expr->right,T_NONE);
		comp_num(OP_APARAM,expr->val,type);
		expr->type = type;
		break;

	case OP_CHKTYPE:
	case OP_IFTRUE:
		error("internal error in gencode()");

	case OP_IFFALSE:
		gencode(expr->left,T_NONE);
		lc1 = LC;
		if( expr->left->type == T_NONE )
			comp_num(OP_IFFALSE,0,0);
		else if( expr->left->type == T_NUMBER )
			comp_num(OP_IFN_FALSE,0,0);
		else if( expr->left->type == T_STRING )
			comp_num(OP_IFS_FALSE,0,0);
		else
			error("first operand of ?: has an illegal type");

		gencode(expr->right->left,type);
		if( !(expr->right->left->type & type) )
			error("middle operand of ?: has an illegal type");

		lc2 = LC;
		comp_num(OP_GOTO,0,0);

		gencode(expr->right->right,type);
		if( !(expr->right->right->type & type) )
			error("last operand of ?: has an illegal type");

		Program[ lc1 ].val = lc2+1;
		Program[ lc2 ].val = LC;

		if( expr->right->right->type == T_NONE ||
					expr->right->left->type == T_NONE )
			expr->type = T_NONE;
		else
			expr->type = type;

		free(expr->left);
		free(expr->right->left);
		free(expr->right->right);
		free(expr->right);
		break;

	case OP_INFIRST:
		error("internal error in gencode()");

	case OP_INNEXT:
		error("internal error in gencode()");

	case OP_ARG:
		error("internal error in gencode()");

	default:
		error("internal error in gencode()");
	}

}

char *initcompiler()
{
	Program = (struct object *) malloc(PROG_INIT*sizeof(struct object));
	Progsize = PROG_INIT;
	if( Program == NULL ) return "out of memory";
	LC = 0;
	return NULL;
}

closecompiler()
{
	if( LC1 >= 0 )
		Program[ LC1 ].val = LC;
	if( LC2 >= 0 )
		Program[ LC2 ].val = LC;
	comp_num(OP_END,0,0);
	comp_str(OP_POP,rhfilename,lineno);
}

#ifdef DEBUG
char *dt(type) {
	static char buf[ SMALLBUF ];
	switch(type) {
	case 0:		return("no type");
	case T_NONE:	return("unknown/any type");
	case T_NUMBER:	return("number");
	case T_STRING:	return("string");
	case T_ARRAY:	return("array");
	case T_LVAL:	return("l-value");
	case BREAK:	return("BREAK");
	case NEXT:	return("NEXT");
	case CONTINUE:	return("CONTINUE");
	default:	sprintf(buf,"Unknown value: %d",type);
			return(buf);
	}
}

showinstr(pc,s,type)
char *s;
{
	printf("[%-3d] %-15.15s, type=%-20.20s, ",pc,s,dt(Program[pc].type));
	if( type )
		printf("value=%s\n",Program[pc].str);
	else
		printf("value=%d\n",Program[pc].val);
}

show_it(p,i)
struct object *p;
{
	switch( p->opcode ) {
	case OP_BUILTIN: showinstr(i,"OP_BUILTIN",0); break;
	case OP_CALL: showinstr(i,"OP_CALL",0); break;
	case OP_RET: showinstr(i,"OP_RET",0); break;
	case OP_GOTO: showinstr(i,"OP_GOTO",0); break;
	case OP_END: showinstr(i,"OP_END",0); break;
	case OP_IFTRUE: showinstr(i,"OP_IFTRUE",0); break;
	case OP_IFN_TRUE: showinstr(i,"OP_IFN_TRUE",0); break;
	case OP_IFS_TRUE: showinstr(i,"OP_IFS_TRUE",0); break;
	case OP_IFFALSE: showinstr(i,"OP_IFFALSE",0); break;
	case OP_IFN_FALSE: showinstr(i,"OP_IFN_FALSE",0); break;
	case OP_IFS_FALSE: showinstr(i,"OP_IFS_FALSE",0); break;
	case OP_POP: showinstr(i,"OP_POP",0); break;
	case OP_NOT: showinstr(i,"OP_NOT",0); break;
	case OP_NEG: showinstr(i,"OP_NEG",0); break;
	case OP_BNOT: showinstr(i,"OP_BNOT",0); break;
	case OP_MUL: showinstr(i,"OP_MUL",0); break;
	case OP_DIV: showinstr(i,"OP_DIV",0); break;
	case OP_MOD: showinstr(i,"OP_MOD",0); break;
	case OP_ADD: showinstr(i,"OP_ADD",0); break;
	case OP_SUB: showinstr(i,"OP_SUB",0); break;
	case OP_BOR: showinstr(i,"OP_BOR",0); break;
	case OP_XOR: showinstr(i,"OP_XOR",0); break;
	case OP_BAND: showinstr(i,"OP_BAND",0); break;
	case OP_SHL: showinstr(i,"OP_SHL",0); break;
	case OP_SHR: showinstr(i,"OP_SHR",0); break;
	case OP_AND1: showinstr(i,"OP_AND1",0); break;
	case OP_AND2: showinstr(i,"OP_AND2",0); break;
	case OP_A1_NUM: showinstr(i,"OP_A1_NUM",0); break;
	case OP_A1_STR: showinstr(i,"OP_A1_STR",0); break;
	case OP_A2_NUM: showinstr(i,"OP_A2_NUM",0); break;
	case OP_A2_STR: showinstr(i,"OP_A2_STR",0); break;
	case OP_OR1: showinstr(i,"OP_OR1",0); break;
	case OP_OR2: showinstr(i,"OP_OR2",0); break;
	case OP_OR1_NUM: showinstr(i,"OP_OR1_NUM",0); break;
	case OP_OR1_STR: showinstr(i,"OP_OR1_STR",0); break;
	case OP_OR2_NUM: showinstr(i,"OP_OR2_NUM",0); break;
	case OP_OR2_STR: showinstr(i,"OP_OR2_STR",0); break;

	case OP_EQ: showinstr(i,"OP_EQ",0); break;
	case OP_NE: showinstr(i,"OP_NE",0); break;
	case OP_GT: showinstr(i,"OP_GT",0); break;
	case OP_GE: showinstr(i,"OP_GE",0); break;
	case OP_LT: showinstr(i,"OP_LT",0); break;
	case OP_LE: showinstr(i,"OP_LE",0); break;
	case OP_NUMEQ: showinstr(i,"OP_NUMEQ",0); break;
	case OP_NUMNE: showinstr(i,"OP_NUMNE",0); break;
	case OP_NUMGT: showinstr(i,"OP_NUMGT",0); break;
	case OP_NUMGE: showinstr(i,"OP_NUMGE",0); break;
	case OP_NUMLT: showinstr(i,"OP_NUMLT",0); break;
	case OP_NUMLE: showinstr(i,"OP_NUMLE",0); break;
	case OP_STREQ: showinstr(i,"OP_STREQ",0); break;
	case OP_STRNE: showinstr(i,"OP_STRNE",0); break;
	case OP_STRGT: showinstr(i,"OP_STRGT",0); break;
	case OP_STRGE: showinstr(i,"OP_STRGE",0); break;
	case OP_STRLT: showinstr(i,"OP_STRLT",0); break;
	case OP_STRLE: showinstr(i,"OP_STRLE",0); break;

	case OP_PLUSPLUS: showinstr(i,"OP_PLUSPLUS",0); break;
	case OP_MINUSMINUS: showinstr(i,"OP_MINUSMINUS",0); break;

	case OP_ASSIGN: showinstr(i,"OP_ASSIGN",0); break;
	case OP_ASS_NUM: showinstr(i,"OP_ASS_NUM",0); break;
	case OP_ASS_STR: showinstr(i,"OP_ASS_STR",0); break;
	case OP_ADDOP: showinstr(i,"OP_ADDOP",0); break;
	case OP_SUBOP: showinstr(i,"OP_SUBOP",0); break;
	case OP_MULOP: showinstr(i,"OP_MULOP",0); break;
	case OP_DIVOP: showinstr(i,"OP_DIVOP",0); break;
	case OP_MODOP: showinstr(i,"OP_MODOP",0); break;
	case OP_OROP: showinstr(i,"OP_OROP",0); break;
	case OP_ANDOP: showinstr(i,"OP_ANDOP",0); break;
	case OP_LSHOP: showinstr(i,"OP_LSHOP",0); break;
	case OP_RSHOP: showinstr(i,"OP_RSHOP",0); break;
	case OP_XOROP: showinstr(i,"OP_XOROP",0); break;
	case OP_NUMBER: showinstr(i,"OP_NUMBER",0); break;
	case OP_STRING: showinstr(i,"OP_STRING",1); break;
	case OP_VAR: showinstr(i,"OP_VAR",0); break;
	case OP_AVAR: showinstr(i,"OP_AVAR",0); break;
	case OP_PARAM: showinstr(i,"OP_PARAM",0); break;
	case OP_APARAM: showinstr(i,"OP_APARAM",0); break;
	case OP_CHKTYPE: showinstr(i,"OP_CHKTYPE",0); break;
	case OP_INFIRST: showinstr(i,"OP_INFIRST",0); break;
	case OP_INNEXT: showinstr(i,"OP_INNEXT",0); break;
	case OP_ARG: showinstr(i,"OP_ARG",0); break;
	default:
		error("internal error");
	}
}

dumpprogram()
{
	int i;

	printf("-----------\n");
	for(i=0; i<LC; i++) {
		show_it(&Program[i],i);
	}
	printf("-----------\n");
	printf("Entry point = %d\n", startLC );
}
#endif

Return To Portfolio Home

compilers • parsers • translators • C++ • yacc &bull lex • bison • unix • windows • eiffel • grammars