📄 engine.cpp
字号:
/************************************************************************ Copyright (C) 2000 Trolltech AS. All rights reserved.**** This file is part of Qtopia Environment.**** This file may be distributed and/or modified under the terms of the** GNU General Public License version 2 as published by the Free Software** Foundation and appearing in the file LICENSE.GPL included in the** packaging of this file.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.**** See http://www.trolltech.com/gpl/ for GPL licensing information.**** Contact info@trolltech.com if any conditions of this licensing are** not clear to you.************************************************************************/#include "engine.h"#include <qtopia/qpeapplication.h>#include <qtopia/calc/doubleinstruction.h>#ifdef ENABLE_FRACTION#include <qtopia/calc/fractioninstruction.h>#endif#ifdef ENABLE_INTEGER#include <qtopia/calc/integerinstruction.h>#endif//#define QTEST// Bracesclass iBraceOpen:public Instruction {public: iBraceOpen():Instruction(){}; ~iBraceOpen(){}; Data *eval(Data *);};class BraceOpen:public InstructionDescription {public: BraceOpen(); ~BraceOpen(); Instruction *getInstruction();};BraceOpen::BraceOpen():InstructionDescription() { instructionName = "Open brace"; // No tr typeOne = typeTwo = type = "NONE"; // No tr precedence = 50;};BraceOpen::~BraceOpen(){};void Engine::closeBrace () { braceCount++; Data *accPtr = acc; acc = evalStack(accPtr,TRUE); if (accPtr != acc) delete accPtr; updateDisplay();}Data *iBraceOpen::eval(Data *d) { systemEngine->decBraceCount(); return d;}Instruction *BraceOpen::getInstruction() { return new iBraceOpen();}Engine::Engine() { // Variable initialisation state = sStart; emptyDataCache = mem = acc = k = 0; kDesc = 0; lcd = 0;#ifdef NEW_STYLE_DISPLAY lcdPainter = 0;#endif memMark = kMark = 0; braceCount = previousInstructionsPrecedence = 0; secondaryReset = FALSE; currentType = "NONE"; // No tr list.setAutoDelete(TRUE); // Register the common instructions // Double InstructionDescription *da = new AddDoubleDouble(); registerInstruction(da); da = new MultiplyDoubleDouble(); registerInstruction(da); da = new SubtractDoubleDouble(); registerInstruction(da); da = new DivideDoubleDouble(); registerInstruction(da); da = new DoubleFactory(); registerInstruction(da); da = new DoubleCopy(); registerInstruction(da); da = new DoublePow(); registerInstruction(da); da = new DoubleExp(); registerInstruction(da); da = new DoubleSin(); registerInstruction(da); da = new DoubleCos(); registerInstruction(da); da = new DoubleTan(); registerInstruction(da); da = new DoubleASin(); registerInstruction(da); da = new DoubleACos(); registerInstruction(da); da = new DoubleATan(); registerInstruction(da); da = new DoubleLog(); registerInstruction(da); da = new DoubleLn(); registerInstruction(da); da = new DoubleOneOverX(); registerInstruction(da); da = new DoubleFactorial(); registerInstruction(da); da = new DoubleSquareRoot(); registerInstruction(da); da = new DoubleCubeRoot(); registerInstruction(da); da = new DoubleXRootY(); registerInstruction(da); da = new DoubleSquare(); registerInstruction(da); da = new DoubleNegate(); registerInstruction(da);#ifdef ENABLE_FRACTION da = new FractionCopy(); registerInstruction(da); da = new FractionFactory(); registerInstruction(da); da = new ConvertDoubleFraction(); registerInstruction(da); da = new AddFractionFraction(); registerInstruction(da); da = new SubtractFractionFraction(); registerInstruction(da); da = new MultiplyFractionFraction(); registerInstruction(da); da = new DivideFractionFraction(); registerInstruction(da); da = new ConvertFractionDouble(); registerInstruction(da);#endif#ifdef ENABLE_INTEGER da = new ConvertIntDouble(); registerInstruction(da);#endif // System da = new BraceOpen(); registerInstruction(da);}Engine::~Engine() { stack.clear(); iStack.clear(); dStack.clear(); delete acc; if (mem != acc) delete mem;};void Engine::registerInstruction(InstructionDescription *d) { #ifdef QTESTqDebug("registerInstruction - %s for %s",d->instructionName.latin1(),d->type.latin1()); // No tr#endif InstructionDescription *tmp; for (uint it = 0; it < list.count(); it++) { tmp = list.at(it); if (tmp->instructionName == d->instructionName && tmp->typeOne == d->typeOne && tmp->typeTwo == d->typeTwo) return; } list.append(d);}Instruction * Engine::resolveInstruction(QString name) { QString type = currentType;#ifdef QTESTqDebug("resolveInstruction(%s)",name.latin1()); // No tr#endif InstructionDescription *id = resolveDescription(name); if (!id) return 0; return resolveInstruction(id);}Instruction * Engine::resolveInstruction(InstructionDescription *d) { if (!d) return 0;#ifdef QTESTqDebug("Searching for %s %s %s in %d", // No tr d->instructionName.latin1(), d->typeOne.latin1(), d->typeTwo.latin1(), list.count());#endif // Create a shortlist of instructions with the same name QList<InstructionDescription> shortList; InstructionDescription *tmp; uint it = 0; for (; it < list.count(); it++) { tmp = list.at(it); if (tmp->instructionName == d->instructionName) shortList.append(list.at(it)); } // No instructions by that name have been found if (!shortList.count()) {#ifdef QTESTqDebug("None found by that name"); // No tr#endif return new Instruction(); } Instruction *ret; // Try to match exactly at first for (it = 0; it < shortList.count(); it++) { tmp = shortList.at(it); if (tmp->typeOne == d->typeOne && tmp->typeTwo == d->typeTwo) {#ifdef QTESTqDebug("Matched %s %s %s",tmp->instructionName.latin1(), // No tr tmp->typeOne.latin1(), tmp->typeTwo.latin1());#endif ret = tmp->getInstruction(); ret->num = d->num; return ret; } }#ifdef QTESTqDebug("No match found"); // No tr#endif // Search for conversions that will let what we have work // Eventually weighting should be here as well... for (it = 0; it < shortList.count(); it++) { tmp = shortList.at(it); InstructionDescription *tmp2; // Search for ops that only require one side to be converted for (uint it2 = 0; it < list.count(); it2++) { tmp2 = list.at(it2); if ( tmp->typeTwo == currentType && tmp2->typeOne == currentType && tmp2->typeTwo == tmp->typeOne && tmp2->instructionName == "Convert" ) { // No tr // Convert ret = tmp2->getInstruction(); ret->num = d->num; // eval delete ret; // crash here... // Now return the actual instruction ret = tmp->getInstruction(); ret->num = d->num; return ret; } else if ( tmp->typeOne == currentType && tmp->typeOne == currentType && tmp2->type == tmp->typeTwo && tmp2->instructionName == "Convert" ) { // No tr // Convert ret = tmp2->getInstruction(); ret->num = d->num; Data *accPtr = acc; acc = ret->eval(accPtr); if ( accPtr != acc ) delete accPtr; delete ret; // Now return the actual instruction ret = tmp->getInstruction(); ret->num = d->num; return ret; } } } return new Instruction();}#ifdef NEW_CONVERTint cheapestTotal;IMP *cheapestOne = 0;IMP *cheapestTwo = 0; for (c in shortList) { QList<instructionAndPath> allOfThem; IMP *one = calcShortestPath(c.typeOne,tmp.typeOne); IMP *two = calcShortestPath(c.typeTwo,tmp.typeTwo); int totalcost = one->cost + two->cost; if (totalcost < cheapestTotal || !cheapestOne || !cheapestTwo) { delete cheapestOne; delete cheapestTwo; cheapestTotal = totalcost; cheapestOne = one; cheapestTwo = two; } else { delete one; delete two; }}struct INP { QList<InstructionDescription> path; int cost;};QList<QList<InstructionDescription>> successfulPaths; INP *calcShortestPath(QString,QString) { // this wont work, gotta do it twice and add them remember!!!! int cheapestCost; QList<InstructionDescription> cheapestPath; successfulPaths.clear(); if (birth doesnt exist) { InstructionDescription birth; birth->typeOne = "WOMB"; // No tr birth->typeTwo = tmp->typeOne; register(birth); } QList<InstructionDescription> life = birth; getAPath(life); for (i in successfulPaths) { if (i.cost() < cheapest) { cheapestCost = i.cost(); cheapestPath = i; } } if (cheapestPath.isEmpty()) return NULL; IMP *ret = new IMP; ret->path = cheapestPath; ret->cost = cheapestCost; return ret; }QString destination;void getAPath(QList<InstructionDescription> stepsIveTaken) { QList<InstructionDescription> exits = getAllExits(stepsIveTaken); if (!exits.isEmpty() ) { for (i in exits) { if (i->typeTwo == destination) { successfulPaths += (stepsIveTaken + i); } else { getAPath(stepsIveTaken + i); } } }}QList<InstructionDescription> Engine::getAllExits(QList<InstructionDescription> stepsIveTaken) P QList<InstructionDescription> exits; InstructionDescription lastStep = stepsIveTaken.last(); QString thisPlace = lastStep.typeTwo; for (i in list) { if ( i->typeOne == thisPlace && !stepsIveTaken.contains (i) ) { exits += i; } } return exits;}#endif// Stackvoid Engine::evaluate() { Data *accPtr = acc; acc = evalStack(accPtr,FALSE); if (accPtr != acc) delete accPtr; updateDisplay(); if ( state != sError ) state = sStart; braceCount = 0;}Data *Engine::evalStack(Data *intermediate,bool inbrace,int p) { if (state != sError) { InstructionDescription *id; Instruction *i; while (!stack.isEmpty () && (braceCount || !inbrace) && state != sError && (p <= stack.top()->precedence || p == 0) ) { // Pop the next instruction id = stack.pop(); // Compare precedence with the next instruction on the stack if (!stack.isEmpty ()) { // Recurse into next instruction if necessary if (p) { if (p <= stack.top()->precedence) { Data *numPtr = id->num; id->num = evalStack(numPtr,inbrace,p); if (numPtr != id->num) delete numPtr; } } else if (id->precedence <= stack.top()->precedence) { Data *numPtr = id->num; id->num = evalStack(numPtr,inbrace,id->precedence); if (numPtr != id->num) delete numPtr; } } i = resolveInstruction(id); i->num = id->num; // Evaluate Data *ptr = intermediate; intermediate = i->eval(ptr); if (ptr != intermediate) { delete ptr; } if (i->num != intermediate && i->num != ptr) { delete i->num; } delete i; delete id; } } return intermediate;}// Miscellaneous functionsvoid Engine::dualReset() { if (secondaryReset) { hardReset(); } else { softReset(); secondaryReset = TRUE; }}void Engine::softReset(bool update) {#ifdef NEW_STYLE_STACK if (dStack.isEmpty()) executeInstructionOnStack("Factory",dStack); // No tr if (dStack.isEmpty()) qDebug("factory didnt work"); // No tr dStack.top()->clear();#else if (acc) acc->clear(); else executeInstructionOnStack("Factory",stack); // No tr#endif state = sStart; if (update) updateDisplay();}void Engine::hardReset() { stack.clear(); dStack.clear(); iStack.clear(); braceCount = 0; secondaryReset = FALSE; softReset();}// Input and outputInstructionDescription *Engine::resolveDescription(QString name) { QString type = currentType;#ifdef QTESTqDebug("resolveDescription(%s, %s)",name.latin1(),type.latin1()); // No tr#endif InstructionDescription *id; for (uint i = 0;i < list.count();i++) { id = list.at(i);#ifdef QTESTqDebug(" - comparing %s for %s",id->instructionName.latin1(),id->type.latin1()); // No tr#endif if (id->instructionName == name && id->type == type) return id; } return 0;}#ifdef NEW_STYLE_STACKvoid Engine::immediateInstruction(QString name) {#ifdef QTESTqDebug("immediateInstruction(%s)",name.latin1()); // No tr#endif if (state == sError || name.isEmpty()) return; previousInstructionsPrecedence = 0; secondaryReset = FALSE; executeInstructionOnStack(name,stack); updateDisplay();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -