--- trunk/src/selection/SelectionEvaluator.cpp 2005/02/01 06:55:00 277 +++ trunk/src/selection/SelectionEvaluator.cpp 2005/02/03 23:14:05 283 @@ -39,8 +39,296 @@ * such damages. */ +#include #include "selection/SelectionEvaluator.hpp" +#include "primitives/Atom.hpp" +#include "primitives/DirectionalAtom.hpp" +#include "primitives/RigidBody.hpp" +#include "primitives/Molecule.hpp" + namespace oopse { +SelectionEvaluator::SelectionEvaluator(SimInfo* si, const std::string& script) : info(si), finder(info){ +} + +bool SelectionEvaluator::loadScript(const std::string& filename, const std::string& script) { + this->filename = filename; + this->script = script; + if (! compiler.compile(filename, script)) { + error = true; + errorMessage = compiler.getErrorMessage(); + return false; + } + + pc = 0; + aatoken = compiler.getAatokenCompiled(); + linenumbers = compiler.getLineNumbers(); + lineIndices = compiler.getLineIndices(); + return true; } + +void SelectionEvaluator::clearState() { + for (int i = scriptLevelMax; --i >= 0; ) + stack[i].clear(); + scriptLevel = 0; + error = false; + errorMessage = ""; +} + +bool SelectionEvaluator::loadScriptString(const std::string& script) { + clearState(); + return loadScript("", script); +} + +bool SelectionEvaluator::loadScriptFile(const std::string& filename) { + clearState(); + return loadScriptFileInternal(filename); +} + +bool SelectionEvaluator::loadScriptFileInternal(const std::string & filename) { + return true; /**@todo */ +} + +void SelectionEvaluator::instructionDispatchLoop(){ + + while ( pc < aatoken.size()) { + statement = aatoken[pc++]; + statementLength = statement.size(); + Token token = statement[0]; + switch (token.tok) { + case Token::define: + define(); + break; + case Token::select: + select(); + break; + default: + unrecognizedCommand(token); + return; + } + } +} + + BitSet SelectionEvaluator::expression(const std::vector& code, int pcStart) { + BitSet bs; + std::stack stack; + + for (int pc = pcStart; ; ++pc) { + Token instruction = code[pc]; + + switch (instruction.tok) { + case Token::expressionBegin: + break; + case Token::expressionEnd: + break; + case Token::all: + bs = BitSet(nStuntDouble); + bs.setAll(); + stack.push(bs); + break; + case Token::none: + bs = BitSet(nStuntDouble); + stack.push(bs); + break; + case Token::opOr: + bs = stack.top(); + stack.pop(); + stack.top() |= bs; + break; + case Token::opAnd: + bs = stack.top(); + stack.pop(); + stack.top() &= bs; + break; + case Token::opNot: + stack.top().flip(); + break; + case Token::within: + + withinInstruction(instruction, stack.top()); + break; + //case Token::selected: + // stack.push(getSelectionSet()); + // break; + case Token::name: + stack.push(nameInstruction(boost::any_cast(instruction.value))); + break; + break; + case Token::identifier: + stack.push(lookupValue(boost::any_cast(instruction.value))); + break; + case Token::opLT: + case Token::opLE: + case Token::opGE: + case Token::opGT: + case Token::opEQ: + case Token::opNE: + stack.push(comparatorInstruction(instruction)); + break; + default: + unrecognizedExpression(); + } + } + if (stack.size() != 1) + evalError("atom expression compiler error - stack over/underflow"); + + return stack.top(); + } + + + +BitSet SelectionEvaluator::comparatorInstruction(const Token& instruction) { + int comparator = instruction.tok; + int property = instruction.intValue; + float comparisonValue = boost::any_cast(instruction.value); + float propertyValue; + BitSet bs(nStuntDouble); + + SimInfo::MoleculeIterator mi; + Molecule* mol; + Molecule::AtomIterator ai; + Atom* atom; + Molecule::RigidBodyIterator rbIter; + RigidBody* rb; + + for (mol = info->beginMolecule(mi); mol != NULL; mol = info->nextMolecule(mi)) { + + for(atom = mol->beginAtom(ai); atom != NULL; atom = mol->nextAtom(ai)) { + compareProperty(atom, bs, property, comparator, comparisonValue); + } + + //change the positions of atoms which belong to the rigidbodies + for (rb = mol->beginRigidBody(rbIter); rb != NULL; rb = mol->nextRigidBody(rbIter)) { + compareProperty(rb, bs, property, comparator, comparisonValue); + } + } + + return bs; +} + +void SelectionEvaluator::compareProperty(StuntDouble* sd, BitSet& bs, int property, int comparator, float comparisonValue) { + double propertyValue; + switch (property) { + case Token::mass: + propertyValue = sd->getMass(); + break; + case Token::charge: + return; + //break; + case Token::dipole: + return; + //break; + default: + unrecognizedAtomProperty(property); + } + + bool match = false; + switch (comparator) { + case Token::opLT: + match = propertyValue < comparisonValue; + break; + case Token::opLE: + match = propertyValue <= comparisonValue; + break; + case Token::opGE: + match = propertyValue >= comparisonValue; + break; + case Token::opGT: + match = propertyValue > comparisonValue; + break; + case Token::opEQ: + match = propertyValue == comparisonValue; + break; + case Token::opNE: + match = propertyValue != comparisonValue; + break; + } + if (match) + bs.setBitOn(sd->getGlobalIndex()); + +} + +void SelectionEvaluator::withinInstruction(const Token& instruction, BitSet& bs){ + + boost::any withinSpec = instruction.value; + if (withinSpec.type() == typeid(float)){ + // + return; + } + + evalError("Unrecognized within parameter"); +} + +void SelectionEvaluator::define() { + assert(statement.size() >= 3); + + std::string variable = boost::any_cast(statement[1].value); + + variables.insert(std::make_pair(variable, expression(statement, 2))); +} + + +/** @todo */ +void SelectionEvaluator::predefine(const std::string& script) { + + if (compiler.compile("#predefine", script)) { + std::vector > aatoken = compiler.getAatokenCompiled(); + if (aatoken.size() != 1) { + evalError("predefinition does not have exactly 1 command:" + + script); + return; + } + std::vector statement = aatoken[0]; + if (statement.size() > 2) { + int tok = statement[1].tok; + if (tok == Token::identifier || (tok & Token::predefinedset) == Token::predefinedset) { + std::string variable = boost::any_cast(statement[1].value); + variables.insert(std::make_pair(variable, statement)); + + } else { + evalError("invalid variable name:" + script); + } + }else { + evalError("bad predefinition length:" + script); + } + + + } else { + evalError("predefined set compile error:" + script + + "\ncompile error:" + compiler.getErrorMessage()); + } + +} + +void SelectionEvaluator::select(){ + //viewer.setSelectionSet(expression(statement, 1)); +} + +BitSet SelectionEvaluator::lookupValue(const std::string& variable){ + + std::map::iterator i = variables.find(variable); + + if (i != variables.end()) { + if (i->second.type() == typeid(BitSet)) { + return boost::any_cast(i->second); + } else if (i->second.type() == typeid(std::vector)){ + BitSet bs = expression(boost::any_cast >(i->second), 2); + i->second = bs; /**@todo fixme */ + return bs; + } + } else { + unrecognizedIdentifier(variable); + } +} + +BitSet SelectionEvaluator::nameInstruction(const std::string& name){ + BitSet bs(nStuntDouble); + + bool hasError = finder.match(name, bs); + + return bs; +} + + +}