/*========================================================================= codegen.cpp Author: PKG Created: Project: Spongebob Purpose: Copyright (c) 2000 Climax Development Ltd ===========================================================================*/ /*---------------------------------------------------------------------- Includes -------- */ #include "codegen.h" #ifndef _LEXER_H #include "lexer.h" #endif #ifndef _PARSER_H #include "parser.h" #endif #ifndef __FUNCTION_H__ #include "function.h" #endif /* Std Lib ------- */ #include #include /* Data ---- */ /*---------------------------------------------------------------------- Tyepdefs && Defines ------------------- */ /*---------------------------------------------------------------------- Structure defintions -------------------- */ /*---------------------------------------------------------------------- Function Prototypes ------------------- */ /*---------------------------------------------------------------------- Vars ---- */ static FILE *s_fhOutput=NULL; CTreeNode *s_baseTreeNode=NULL; mylexer s_lexer; myparser s_parser; /*---------------------------------------------------------------------- Function: Purpose: Params: Returns: ---------------------------------------------------------------------- */ extern int parseFile(char *_filename,CTreeNode *_baseNode) { int ret; ret=YYEXIT_FAILURE; if(s_parser.yycreate(&s_lexer)) { if(s_lexer.yycreate(&s_parser)) { if(s_lexer.openInputFile(_filename)==(int)true) { s_parser.setCurrentLexer(&s_lexer); s_parser.setBaseNode(_baseNode); ret=s_parser.yyparse(); // s_lexer.closeInputFile(); } } } return ret; } /*---------------------------------------------------------------------- Function: Purpose: Params: Returns: ---------------------------------------------------------------------- */ extern int openOutputFile(char *_filename) { int ret=1; if((s_fhOutput=fopen(_filename,"wb"))==NULL) { ret=0; } return ret; } /*---------------------------------------------------------------------- Function: Purpose: Params: Returns: ---------------------------------------------------------------------- */ extern int closeOutputFile() { fclose(s_fhOutput); return 0; } /*---------------------------------------------------------------------- Function: Purpose: Params: Returns: ---------------------------------------------------------------------- */ CTreeNode::CTreeNode(NodeType _type) { m_type=_type; m_children[0]=NULL; m_children[1]=NULL; m_children[2]=NULL; m_numChildren=0; } CTreeNode::CTreeNode(NodeType _type,CTreeNode *child1) { m_type=_type; m_children[0]=child1; m_children[1]=NULL; m_children[2]=NULL; m_numChildren=1; } CTreeNode::CTreeNode(NodeType _type,CTreeNode *child1,CTreeNode *child2) { m_type=_type; m_children[0]=child1; m_children[1]=child2; m_children[2]=NULL; m_numChildren=2; } CTreeNode::CTreeNode(NodeType _type,CTreeNode *child1,CTreeNode *child2,CTreeNode *child3) { m_type=_type; m_children[0]=child1; m_children[1]=child2; m_children[2]=child3; m_numChildren=3; } CTreeNode::CTreeNode(NodeType _type,int _data) { m_type=_type; m_children[0]=NULL; m_children[1]=NULL; m_children[2]=NULL; m_numChildren=0; switch(_type) { case VARIABLE_EXPR: m_variableIdx=_data; break; case VALUE_EXPR: m_value=_data; break; case FUNCTION_EXPR: m_functionNumber=_data; break; default: printf("ARSE\n"); break; } } /*---------------------------------------------------------------------- Function: Purpose: Params: Returns: ---------------------------------------------------------------------- */ int CTreeNode::generateCode(int _write) { int codeSize=0; int tmp1,tmp2; switch(m_type) { case STMT_LIST: // list of statements [left-part, right-part] (left-part may be another list) if(m_children[0])codeSize+=m_children[0]->generateCode(_write); if(m_children[1])codeSize+=m_children[1]->generateCode(_write); break; case EMPTY_STMT: // empty statement break; case PRINT_STMT: // print [variable] codeSize+=m_children[0]->generateCode(_write); codeSize+=emit(OP_PRINT,_write); break; case STOP_STMT: // stop codeSize+=emit(OP_STOP,_write); break; case PAUSE_STMT: // pause codeSize+=emit(OP_PAUSE,_write); break; case IF_STMT: // if [expression, ifcode] codeSize+=m_children[0]->generateCode(_write); codeSize+=emit(OP_PUSHVALUE,_write); codeSize+=emit((signed short)m_children[1]->generateCode(false),_write); codeSize+=emit(OP_JMPF,_write); codeSize+=m_children[1]->generateCode(_write); break; case IFELSE_STMT: // if [expression, ifcode, elsecode] codeSize+=m_children[0]->generateCode(_write); codeSize+=emit(OP_PUSHVALUE,_write); codeSize+=emit((signed short)(m_children[1]->generateCode(false)+emit(OP_PUSHVALUE,false)+emit(0,false)+emit(OP_JMP,false)),_write); codeSize+=emit(OP_JMPF,_write); codeSize+=m_children[1]->generateCode(_write); codeSize+=emit(OP_PUSHVALUE,_write); codeSize+=emit((signed short)m_children[2]->generateCode(false),_write); codeSize+=emit(OP_JMP,_write); codeSize+=m_children[2]->generateCode(_write); break; case WHILE_STMT: // while [expression, code] tmp1=m_children[1]->generateCode(false); tmp2=codeSize; codeSize=m_children[0]->generateCode(_write); codeSize+=emit(OP_PUSHVALUE,_write); codeSize+=emit((signed short)tmp1+3,_write); codeSize+=emit(OP_JMPF,_write); codeSize+=m_children[1]->generateCode(_write); codeSize+=emit(OP_PUSHVALUE,_write); codeSize+=emit((signed short)-(codeSize-tmp2+2),_write); codeSize+=emit(OP_JMP,_write); break; case DOWHILE_STMT: // do [code] while [expression] tmp1=m_children[0]->generateCode(false)+m_children[1]->generateCode(false)+3; codeSize=m_children[0]->generateCode(_write); codeSize+=m_children[1]->generateCode(_write); codeSize+=emit(OP_PUSHVALUE,_write); codeSize+=emit((signed short)-tmp1,_write); codeSize+=emit(OP_JMPT,_write); break; case POP_STMT: // pop codeSize+=emit(OP_POP,_write); break; case ASSIGN_EXPR: // assign [variable, number] codeSize+=m_children[1]->generateCode(_write); codeSize+=emit(OP_PUSHVALUE,_write); codeSize+=emit(m_children[0]->getVariableIdx(),_write); codeSize+=emit(OP_ASSIGN,_write); break; case EQUAL_EXPR: // == [variable, value] codeSize+=m_children[1]->generateCode(_write); codeSize+=m_children[0]->generateCode(_write); codeSize+=emit(OP_IS_EQUAL_VALUE,_write); break; case NOTEQUAL_EXPR: // != [variable, value] codeSize+=m_children[1]->generateCode(_write); codeSize+=m_children[0]->generateCode(_write); codeSize+=emit(OP_IS_NOTEQUAL_VALUE,_write); break; case LESSTHAN_EXPR: // [variable, value] codeSize+=m_children[1]->generateCode(_write); codeSize+=m_children[0]->generateCode(_write); codeSize+=emit(OP_IS_LESSTHAN_VALUE,_write); break; case GREATERTHAN_EXPR: // [variable, value] codeSize+=m_children[1]->generateCode(_write); codeSize+=m_children[0]->generateCode(_write); codeSize+=emit(OP_IS_GREATERTHAN_VALUE,_write); break; case VARIABLE_EXPR: // variable case VALUE_EXPR: // value if(m_numChildren) codeSize+=emitValue(m_children[0],_write); else codeSize+=emitValue(this,_write); break; case PLUS_EXPR: // + [value, value] codeSize+=m_children[0]->generateCode(_write); codeSize+=m_children[1]->generateCode(_write); codeSize+=emit(OP_ADD,_write); break; case SUBTRACT_EXPR: // - [value, value] codeSize+=m_children[0]->generateCode(_write); codeSize+=m_children[1]->generateCode(_write); codeSize+=emit(OP_NEG,_write); codeSize+=emit(OP_ADD,_write); break; case MULTIPLY_EXPR: // * [value, value] codeSize+=m_children[1]->generateCode(_write); codeSize+=m_children[0]->generateCode(_write); codeSize+=emit(OP_MULTIPLY,_write); break; case DIVIDE_EXPR: // / [value, value] codeSize+=m_children[1]->generateCode(_write); codeSize+=m_children[0]->generateCode(_write); codeSize+=emit(OP_DIVIDE,_write); break; case FUNCTION_EXPR: // function [functionNumber] codeSize+=emit(OP_CALL_FUNCTION,_write); codeSize+=emit(getFunctionNumber(),_write); codeSize+=emit(getFunctionArgCount(getFunctionNumber()),_write); break; default: printf("UNHANDLED CASE %d\n",m_type); exit(-2); break; } return codeSize; } /*---------------------------------------------------------------------- Function: Purpose: Params: Returns: ---------------------------------------------------------------------- */ int CTreeNode::emit(unsigned short _data,int _write) { if(_write) { fwrite(&_data,sizeof(unsigned short),1,s_fhOutput); } return 1; } int CTreeNode::emitValue(CTreeNode *_child,int _write) { int codeSize=0; switch(_child->getType()) { case VARIABLE_EXPR: codeSize=emit(OP_PUSHVARVALUE,_write)+emit(_child->getVariableIdx(),_write); break; case VALUE_EXPR: codeSize=emit(OP_PUSHVALUE,_write)+emit(_child->getValue(),_write); break; default: printf("INTERNAL ERROR IN emitValue() :(\n"); exit(-2); break; } return codeSize; } /*=========================================================================== end */