IntermediateData *ScriptParser::generateOCode(FunctionData *fdata) { //Z_message("yes"); bool failure = false; vector<ASTFuncDecl *> funcs = fdata->functions; vector<ASTVarDecl *> globals = fdata->globalVars; vector<ASTArrayDecl *> globalas = fdata->globalArrays; //we have no need of newglobals at this point anymore for(vector<ASTVarDecl *>::iterator it = fdata->newGlobalVars.begin(); it != fdata->newGlobalVars.end(); it++) globals.push_back(*it); for(vector<ASTArrayDecl *>::iterator it = fdata->newGlobalArrays.begin(); it != fdata->newGlobalArrays.end(); it++) globalas.push_back(*it); map<string, int> runsymbols = fdata->scriptRunSymbols; SymbolTable *symbols = fdata->symbols; map<string, int> numparams = fdata->numParams; map<string, int> scripttypes = fdata->scriptTypes; map<string, int> thisptr = fdata->thisPtr; delete fdata; LinkTable lt; for(vector<ASTVarDecl *>::iterator it = globals.begin(); it != globals.end(); it++) { int vid2 = symbols->getID(*it); lt.addGlobalVar(vid2); } for(vector<ASTArrayDecl *>::iterator it = globalas.begin(); it != globalas.end(); it++) { int vid2 = symbols->getID(*it); lt.addGlobalVar(vid2); } //Z_message("yes"); //and add the this pointers for(vector<int>::iterator it = symbols->getGlobalPointers().begin(); it != symbols->getGlobalPointers().end(); it++) { lt.addGlobalPointer(*it); } for(vector<ASTFuncDecl *>::iterator it = funcs.begin(); it != funcs.end(); it++) { int fid2 = symbols->getID(*it); lt.functionToLabel(fid2); } //Z_message("yes"); //we now have labels for the functions and ids for the global variables. //we can now generate the code to intialize the globals IntermediateData *rval = new IntermediateData(); //Link against the global symbols, and add their labels map<int, vector<Opcode *> > globalcode = GlobalSymbols::getInst().addSymbolsCode(lt); for(map<int, vector<Opcode *> >::iterator it = globalcode.begin(); it != globalcode.end(); it++) { rval->funcs[it->first] = it->second; } globalcode = FFCSymbols::getInst().addSymbolsCode(lt); for(map<int, vector<Opcode *> >::iterator it = globalcode.begin(); it != globalcode.end(); it++) { rval->funcs[it->first] = it->second; } globalcode = ItemSymbols::getInst().addSymbolsCode(lt); for(map<int, vector<Opcode *> >::iterator it = globalcode.begin(); it != globalcode.end(); it++) { rval->funcs[it->first] = it->second; } globalcode = ItemclassSymbols::getInst().addSymbolsCode(lt); for(map<int, vector<Opcode *> >::iterator it = globalcode.begin(); it != globalcode.end(); it++) { rval->funcs[it->first] = it->second; } globalcode = LinkSymbols::getInst().addSymbolsCode(lt); for(map<int, vector<Opcode *> >::iterator it = globalcode.begin(); it != globalcode.end(); it++) { rval->funcs[it->first] = it->second; } globalcode = ScreenSymbols::getInst().addSymbolsCode(lt); for(map<int, vector<Opcode *> >::iterator it = globalcode.begin(); it != globalcode.end(); it++) { rval->funcs[it->first] = it->second; } globalcode = GameSymbols::getInst().addSymbolsCode(lt); for(map<int, vector<Opcode *> >::iterator it = globalcode.begin(); it != globalcode.end(); it++) { rval->funcs[it->first] = it->second; } globalcode = NPCSymbols::getInst().addSymbolsCode(lt); for(map<int, vector<Opcode *> >::iterator it = globalcode.begin(); it != globalcode.end(); it++) { rval->funcs[it->first] = it->second; } globalcode = LinkWeaponSymbols::getInst().addSymbolsCode(lt); for(map<int, vector<Opcode *> >::iterator it = globalcode.begin(); it != globalcode.end(); it++) { rval->funcs[it->first] = it->second; } globalcode = EnemyWeaponSymbols::getInst().addSymbolsCode(lt); for(map<int, vector<Opcode *> >::iterator it = globalcode.begin(); it != globalcode.end(); it++) { rval->funcs[it->first] = it->second; } //Z_message("yes"); for(vector<ASTVarDecl *>::iterator it = globals.begin(); it != globals.end(); it++) { OpcodeContext oc; oc.linktable = < oc.symbols = symbols; oc.stackframe = NULL; BuildOpcodes bo; (*it)->execute(bo, &oc); if(!bo.isOK()) { failure = true; } vector<Opcode *> code = bo.getResult(); for(vector<Opcode *>::iterator it2 = code.begin(); it2!= code.end(); it2++) { rval->globalsInit.push_back(*it2); } delete *it; //say so long to our lovely data structure the AST } //Z_message("yes"); for(vector<ASTArrayDecl *>::iterator it = globalas.begin(); it != globalas.end(); it++) { OpcodeContext oc; oc.linktable = < oc.symbols = symbols; oc.stackframe = NULL; BuildOpcodes bo; (*it)->execute(bo, &oc); if(!bo.isOK()) { failure = true; } vector<Opcode *> code = bo.getResult(); for(vector<Opcode *>::iterator it2 = code.begin(); it2!= code.end(); it2++) { rval->globalasInit.push_back(*it2); } delete *it; //say so long to our lovely data structure the AST } //Z_message("yes"); //globals have been initialized, now we repeat for the functions for(vector<ASTFuncDecl *>::iterator it = funcs.begin(); it != funcs.end(); it++) { bool isarun = false; string scriptname; for(map<string,int>::iterator it2 = runsymbols.begin(); it2 != runsymbols.end(); it2++) { if(it2->second == symbols->getID(*it)) { isarun=true; scriptname = it2->first; break; } } vector<Opcode *> funccode; //count the number of stack-allocated variables vector<int> stackvars; pair<vector<int> *, SymbolTable *> param = pair<vector<int> *, SymbolTable *>(&stackvars, symbols); CountStackSymbols temp; (*it)->execute(temp, ¶m); int offset = 0; StackFrame sf; //if this is a run, there is the this pointer if(isarun) { sf.addToFrame(thisptr[scriptname], offset); offset += 10000; } //the params are now the first elements of this list //so assign them depths in reverse order for(vector<int>::reverse_iterator it2 = stackvars.rbegin(); it2 != stackvars.rend(); it2++) { sf.addToFrame(*it2, offset); offset += 10000; } //start of the function Opcode *first = new OSetImmediate(new VarArgument(EXP1), new LiteralArgument(0)); first->setLabel(lt.functionToLabel(symbols->getID(*it))); funccode.push_back(first); //push on the 0s int numtoallocate = (unsigned int)stackvars.size()-(unsigned int)symbols->getFuncParams(symbols->getID(*it)).size(); for(int i = 0; i < numtoallocate; i++) { funccode.push_back(new OPushRegister(new VarArgument(EXP1))); } //push on the this, if a script if(isarun) { switch(scripttypes[scriptname]) { case ScriptParser::TYPE_FFC: funccode.push_back(new OSetRegister(new VarArgument(EXP2), new VarArgument(REFFFC))); break; case ScriptParser::TYPE_ITEMCLASS: funccode.push_back(new OSetRegister(new VarArgument(EXP2), new VarArgument(REFITEMCLASS))); break; case ScriptParser::TYPE_GLOBAL: //don't care, we don't have a valid this pointer break; } funccode.push_back(new OPushRegister(new VarArgument(EXP2))); } //set up the stack frame register funccode.push_back(new OSetRegister(new VarArgument(SFRAME), new VarArgument(SP))); OpcodeContext oc; oc.linktable = < oc.symbols = symbols; oc.stackframe = &sf; BuildOpcodes bo; (*it)->execute(bo, &oc); if(!bo.isOK()) failure = true; vector<Opcode *> code = bo.getResult(); for(vector<Opcode *>::iterator it2 = code.begin(); it2 != code.end(); it2++) { funccode.push_back(*it2); } //add appendix code //nop label Opcode *next = new OSetImmediate(new VarArgument(EXP2), new LiteralArgument(0)); next->setLabel(bo.getReturnLabelID()); funccode.push_back(next); //pop off everything for(unsigned int i=0; i< stackvars.size(); i++) { funccode.push_back(new OPopRegister(new VarArgument(EXP2))); } //if it's a main script, quit. if(isarun) funccode.push_back(new OQuit()); else { //pop off the return address funccode.push_back(new OPopRegister(new VarArgument(EXP2))); //and return funccode.push_back(new OGotoRegister(new VarArgument(EXP2))); } rval->funcs[lt.functionToLabel(symbols->getID(*it))]=funccode; delete *it; } //Z_message("yes"); //update the run symbols for(map<string, int>::iterator it = runsymbols.begin(); it != runsymbols.end(); it++) { int labelid = lt.functionToLabel(it->second); rval->scriptRunLabels[it->first] = labelid; rval->numParams[it->first] = numparams[it->first]; rval->scriptTypes[it->first] = scripttypes[it->first]; } delete symbols; //and so long to our beloved ;) symbol table //Z_message("yes"); if(failure) { //delete all kinds of crap if there was a problem :-/ for(map<int, vector<Opcode *> >::iterator it = rval->funcs.begin(); it != rval->funcs.end(); it++) { for(vector<Opcode *>::iterator it2 = it->second.begin(); it2 != it->second.end(); it2++) { delete *it2; } } for(vector<Opcode *>::iterator it = rval->globalsInit.begin(); it != rval->globalsInit.end(); it++) { delete *it; } for(vector<Opcode *>::iterator it = rval->globalasInit.begin(); it != rval->globalasInit.end(); it++) { delete *it; } delete rval; return NULL; } //Z_message("yes"); return rval; }