Foam::scalar Foam::equationReader::getScalarSrcEquationCircRefDetect ( const equationReader * eqnReader, const label equationIndex, const label equationOperationIndex, const label maxStoreIndex, const label storageOffset ) const { const equation& eqn(operator[](equationIndex)); equationOperation& eqOp(eqn[equationOperationIndex]); label zeroSourceIndex = mag(eqOp.sourceIndex()) - 1; // Check for circular references dependents_.setSize(dependents_.size() + 1); dependents_[dependents_.size() - 1] = equationIndex; forAll(dependents_, i) { if (dependents_[i] == zeroSourceIndex) { // Circular reference detected string dependencies; for (label j(i); j < dependents_.size(); j++) { dependencies.append ( operator[](dependents_[j]).name() ); dependencies.append("-->"); } dependencies.append(operator[](dependents_[i]).name()); FatalErrorIn("equationReader::getScalarSrcEquationCircRefDetect") << "Circular reference detected when evaluating " << "the equation for " << eqn.name() << ", given by:" << token::NL << token::TAB << eqn.rawText() << token::NL << "The circular " << "dependency is:" << token::NL << token::TAB << dependencies << abort(FatalError); } } // Launch the reportEmbeddedDispatchFunction: // if (debug) // { // reportEmbeddedDispatchEnabled; // // or: Info << "Embedded equation dispatch." << endl; // } // else // { // reportEmbeddedDispatchDisabled(); // // does nothing // } scalar returnMe ( internalEvaluateScalar(zeroSourceIndex, maxStoreIndex + 1) ); eqOp.assignSourceScalarFunction ( &Foam::equationReader::getScalarSrcEquation ); eqOp.assignSourceScalarFieldFunction ( &Foam::equationReader::getScalarFieldSrcEquation ); // Launch the reportEmbeddedReturnFunction: // if (debug) // { // reportEmbeddedReturnEnabled; // // or: Info << "Return from equation equation." << endl; // } // else // { // reportEmbeddedReturnDisabled(); // // does nothing // } (*this.*reportEmbeddedReturnFunction_)(); //Move one level back up on the dependents_ list if (dependents_.size()) { dependents_.setSize(dependents_.size() - 1); } returnMe *= sign(eqOp.sourceIndex()); return returnMe; }
RSourceIndex::RSourceIndex(const std::string& context, const std::string& code) : context_(context) { // convert code to wide std::wstring wCode = string_utils::utf8ToWide(code, context); // determine where the linebreaks are and initialize an iterator // used for scanning them std::vector<std::size_t> newlineLocs; std::size_t nextNL = 0; while ( (nextNL = wCode.find(L'\n', nextNL)) != std::string::npos ) newlineLocs.push_back(nextNL++); std::vector<std::size_t>::const_iterator newlineIter = newlineLocs.begin(); std::vector<std::size_t>::const_iterator endNewlines = newlineLocs.end(); // tokenize RTokens rTokens(wCode, RTokens::StripWhitespace | RTokens::StripComments); // scan for function, method, and class definitions (track indent level) int braceLevel = 0; std::wstring function(L"function"); std::wstring set(L"set"); std::wstring setGeneric(L"setGeneric"); std::wstring setGroupGeneric(L"setGroupGeneric"); std::wstring setMethod(L"setMethod"); std::wstring setClass(L"setClass"); std::wstring setClassUnion(L"setClassUnion"); std::wstring setRefClass(L"setRefClass"); std::wstring eqOp(L"="); std::wstring assignOp(L"<-"); std::wstring parentAssignOp(L"<<-"); for (std::size_t i=0; i<rTokens.size(); i++) { // initial name, qualifer, and type are nil RSourceItem::Type type = RSourceItem::None; std::wstring name; std::size_t tokenOffset = -1; bool isSetMethod = false; std::vector<RS4MethodParam> signature; // alias the token const RToken& token = rTokens.at(i); // see if this is a begin or end brace and update the level if (token.type() == RToken::LBRACE) { braceLevel++; continue; } else if (token.type() == RToken::RBRACE) { braceLevel--; continue; } // bail for non-identifiers else if (token.type() != RToken::ID) { continue; } // is this a potential method or class definition? if (token.contentStartsWith(set)) { RSourceItem::Type setType = RSourceItem::None; if (token.contentEquals(setMethod)) { isSetMethod = true; setType = RSourceItem::Method; } else if (token.contentEquals(setGeneric) || token.contentEquals(setGroupGeneric)) { setType = RSourceItem::Method; } else if (token.contentEquals(setClass) || token.contentEquals(setClassUnion) || token.contentEquals(setRefClass)) { setType = RSourceItem::Class; } else { continue; } // make sure there are at least 4 more tokens if ( (i + 3) >= rTokens.size()) continue; // check for the rest of the token sequene for a valid call to set* if ( (rTokens.at(i+1).type() != RToken::LPAREN) || (rTokens.at(i+2).type() != RToken::STRING) || (rTokens.at(i+3).type() != RToken::COMMA)) continue; // found a class or method definition (will find location below) type = setType; name = removeQuoteDelims(rTokens.at(i+2).content()); tokenOffset = token.offset(); // if this was a setMethod then try to lookahead for the signature if (isSetMethod) { parseSignature(rTokens.begin() + (i+4), rTokens.end(), &signature); } } // is this a function? else if (token.contentEquals(function)) { // if there is no room for an operator and identifier prior // to the function then bail if (i < 2) continue; // check for an assignment operator const RToken& opToken = rTokens.at(i-1); if ( opToken.type() != RToken::OPER) continue; if (!opToken.isOperator(eqOp) && !opToken.isOperator(assignOp) && !opToken.isOperator(parentAssignOp)) continue; // check for an identifier const RToken& idToken = rTokens.at(i-2); if ( idToken.type() != RToken::ID ) continue; // if there is another previous token make sure it isn't a // comma or an open paren if ( i > 2 ) { const RToken& prevToken = rTokens.at(i-3); if (prevToken.type() == RToken::LPAREN || prevToken.type() == RToken::COMMA) continue; } // if we got this far then this is a function definition type = RSourceItem::Function; name = idToken.content(); tokenOffset = idToken.offset(); } else { continue; } // compute the line by starting at the current line index and // finding the first newline which is after the idToken offset newlineIter = std::upper_bound(newlineIter, endNewlines, tokenOffset); std::size_t line = newlineIter - newlineLocs.begin() + 1; // compute column by comparing the offset to the PREVIOUS newline // (guard against no previous newline) std::size_t column; if (line > 1) column = tokenOffset - *(newlineIter - 1); else column = tokenOffset; // add to index items_.push_back(RSourceItem(type, string_utils::wideToUtf8(name), signature, braceLevel, line, column)); } }
/*** Evaluate this object ***/ Object* SpecialFunction::evaluate() { if(args.size() == 0) throw Excep(getLineNumber(), getColumnNumber(), "Expected argument to special function!"); std::auto_ptr<Object> arg1(args.at(0)->evaluate()); if(id == SPF_INDEX) { if(args.size() != 2) throw Excep(getLineNumber(), getColumnNumber(), "Invalid number of arguments passed to special function!"); std::auto_ptr<Object> arg2(args.at(1)->evaluate()); if(arg2->getType() == OBJ_TEXT) { if(arg1->getType() != OBJ_TEXT) throw InvalidTypeException(getLineNumber(), getColumnNumber(), OBJ_TEXT, arg1->getType(), 1); Text* cast1 = static_cast<Text*>(arg1.get()); Text* cast2 = static_cast<Text*>(arg2.get()); size_t index = cast2->getValue().find(cast1->getValue()); if(index != std::string::npos) return new Integer(index + 1); return new Integer(0); } if(arg2->getType() == OBJ_SEQUENCE) { Sequence* cast = dynamic_cast<Sequence*>(arg2.get()); for(unsigned int i = 0; i < cast->getLength(); i++) { std::auto_ptr<Logical> eqOp(static_cast<Logical*>(Equal(arg1->clone(), cast->getObject(i)->clone()).evaluate())); if(eqOp->getValue() == true) return new Integer(i + 1); } return new Integer(0); } throw InvalidTypeException(getLineNumber(), getColumnNumber(), OBJ_TEXT | OBJ_SEQUENCE, arg2->getType(), 2); } if(args.size() > 1) throw Excep(getLineNumber(), getColumnNumber(), "Invalid number of arguments passed to special function!"); if(id == SPF_ABS) { if(arg1->getType() == OBJ_INTEGER) { Integer* cast = static_cast<Integer*>(arg1.get()); if(cast->getValue() < 0) return new Integer(-cast->getValue()); return new Integer(cast->getValue()); } if(arg1->getType() == OBJ_REAL) { Real* cast = static_cast<Real*>(arg1.get()); if(cast->getValue() < 0) return new Real(-cast->getValue()); return new Real(cast->getValue()); } throw InvalidTypeException(getLineNumber(), getColumnNumber(), OBJ_INTEGER | OBJ_REAL, arg1->getType(), 1); } if(id == SPF_SIGN) { if(arg1->getType() == OBJ_INTEGER) { Integer* cast = static_cast<Integer*>(arg1.get()); if(cast->getValue() < 0) return new Integer(-1); if(cast->getValue() > 0) return new Integer(1); return new Integer(0); } if(arg1->getType() == OBJ_REAL) { Real* cast = static_cast<Real*>(arg1.get()); if(cast->getValue() < 0) return new Integer(-1); if(cast->getValue() > 0) return new Integer(1); return new Integer(0); } throw InvalidTypeException(getLineNumber(), getColumnNumber(), OBJ_INTEGER | OBJ_REAL, arg1->getType(), 1); } if(id == SPF_SQRT) { if(arg1->getType() == OBJ_INTEGER) { Integer* cast = static_cast<Integer*>(arg1.get()); if(cast->getValue() < 0) throw NegativeValueException(getLineNumber(), getColumnNumber(), cast->getValue(), 1); double res = sqrt((double) cast->getValue()); if((long) res == res) return new Integer((long) res); return new Real(res); } if(arg1->getType() == OBJ_REAL) { Real* cast = static_cast<Real*>(arg1.get()); if(cast->getValue() < 0) throw NegativeValueException(getLineNumber(), getColumnNumber(), cast->getValue(), 1); double res = sqrt((double) cast->getValue()); return new Real(res); } throw InvalidTypeException(getLineNumber(), getColumnNumber(), OBJ_INTEGER | OBJ_REAL, arg1->getType(), 1); } if(id == SPF_ENTIER) { if(arg1->getType() == OBJ_INTEGER) { Integer* cast = static_cast<Integer*>(arg1.get()); return new Integer(cast->getValue()); } if(arg1->getType() == OBJ_REAL) { Real* cast = static_cast<Real*>(arg1.get()); return new Integer(floor(cast->getValue())); } throw InvalidTypeException(getLineNumber(), getColumnNumber(), OBJ_INTEGER | OBJ_REAL, arg1->getType(), 1); } if(id == SPF_ROUND) { if(arg1->getType() == OBJ_INTEGER) { Integer* cast = static_cast<Integer*>(arg1.get()); return new Integer(cast->getValue()); } if(arg1->getType() == OBJ_REAL) { Real* cast = static_cast<Real*>(arg1.get()); long rounded = cast->getValue() < 0.0 ? ceil(cast->getValue() - 0.5) : floor(cast->getValue() + 0.5); return new Integer(rounded); } throw InvalidTypeException(getLineNumber(), getColumnNumber(), OBJ_INTEGER | OBJ_REAL, arg1->getType(), 1); } if(id == SPF_RAND) { if(arg1->getType() == OBJ_INTEGER) { Integer* cast = static_cast<Integer*>(arg1.get()); if(cast->getValue() < 0) throw NegativeValueException(getLineNumber(), getColumnNumber(), cast->getValue(), 1); double f = (double) rand() / RAND_MAX; return new Real( f * cast->getValue() ); } if(arg1->getType() == OBJ_REAL) { Real* cast = static_cast<Real*>(arg1.get()); if(cast->getValue() < 0) throw NegativeValueException(getLineNumber(), getColumnNumber(), cast->getValue(), 1); double f = (double) rand() / RAND_MAX; return new Real( f * cast->getValue() ); } throw InvalidTypeException(getLineNumber(), getColumnNumber(), OBJ_INTEGER | OBJ_REAL, arg1->getType(), 1); } if(id == SPF_INTRAND) { if(arg1->getType() == OBJ_INTEGER) { Integer* cast = static_cast<Integer*>(arg1.get()); if(cast->getValue() < 0) throw NegativeValueException(getLineNumber(), getColumnNumber(), cast->getValue(), 1); return new Integer( rand() % cast->getValue() + 1 ); } if(arg1->getType() == OBJ_REAL) { Real* cast = static_cast<Real*>(arg1.get()); if(cast->getValue() < 0) throw NegativeValueException(getLineNumber(), getColumnNumber(), cast->getValue(), 1); return new Integer( rand() % (long) cast->getValue() + 1 ); } throw InvalidTypeException(getLineNumber(), getColumnNumber(), OBJ_INTEGER | OBJ_REAL, arg1->getType(), 1); } if(id == SPF_ISEMPTY) { return new Logical(arg1->getType() == OBJ_EMPTY); } if(id == SPF_ISLOG) { return new Logical(arg1->getType() == OBJ_LOGICAL); } if(id == SPF_ISINT) { return new Logical(arg1->getType() == OBJ_INTEGER); } if(id == SPF_ISREAL) { return new Logical(arg1->getType() == OBJ_REAL); } if(id == SPF_ISTEXT) { return new Logical(arg1->getType() == OBJ_TEXT); } if(id == SPF_ISSEQ) { return new Logical(arg1->getType() == OBJ_SEQUENCE); } if(id == SPF_ISPROC) { return new Logical(arg1->getType() == OBJ_PROCEDURE); } if(id == SPF_ISFUN) { return new Logical(arg1->getType() == OBJ_FUNCTION || arg1->getType() == OBJ_SPFUNCTION); } if(id == SPF_SIN) { if(arg1->getType() == OBJ_INTEGER) { Integer* cast = static_cast<Integer*>(arg1.get()); return new Real(sin((double) cast->getValue())); } if(arg1->getType() == OBJ_REAL) { Real* cast = static_cast<Real*>(arg1.get()); return new Real(sin(cast->getValue())); } throw InvalidTypeException(getLineNumber(), getColumnNumber(), OBJ_INTEGER | OBJ_REAL, arg1->getType(), 1); } if(id == SPF_COS) { if(arg1->getType() == OBJ_INTEGER) { Integer* cast = static_cast<Integer*>(arg1.get()); return new Real(cos((double) cast->getValue())); } if(arg1->getType() == OBJ_REAL) { Real* cast = static_cast<Real*>(arg1.get()); return new Real(cos(cast->getValue())); } throw InvalidTypeException(getLineNumber(), getColumnNumber(), OBJ_INTEGER | OBJ_REAL, arg1->getType(), 1); } if(id == SPF_TG) { if(arg1->getType() == OBJ_INTEGER) { Integer* cast = static_cast<Integer*>(arg1.get()); return new Real(tan((double) cast->getValue())); } if(arg1->getType() == OBJ_REAL) { Real* cast = static_cast<Real*>(arg1.get()); return new Real(tan(cast->getValue())); } throw InvalidTypeException(getLineNumber(), getColumnNumber(), OBJ_INTEGER | OBJ_REAL, arg1->getType(), 1); } if(id == SPF_ARCSIN) { if(arg1->getType() == OBJ_INTEGER) { Integer* cast = static_cast<Integer*>(arg1.get()); if(errno == EDOM) throw new Excep(getLineNumber(), getColumnNumber(), "Invalid value passed to special function!"); return new Real(exp((double) cast->getValue())); } if(arg1->getType() == OBJ_REAL) { Real* cast = static_cast<Real*>(arg1.get()); if(errno == EDOM) throw new Excep(getLineNumber(), getColumnNumber(), "Invalid value passed to special function!"); return new Real(exp(cast->getValue())); } throw InvalidTypeException(getLineNumber(), getColumnNumber(), OBJ_INTEGER | OBJ_REAL, arg1->getType(), 1); } if(id == SPF_ARCTG) { if(arg1->getType() == OBJ_INTEGER) { Integer* cast = static_cast<Integer*>(arg1.get()); if(errno == EDOM) throw new Excep(getLineNumber(), getColumnNumber(), "Invalid value passed to special function!"); return new Real(exp((double) cast->getValue())); } if(arg1->getType() == OBJ_REAL) { Real* cast = static_cast<Real*>(arg1.get()); if(errno == EDOM) throw new Excep(getLineNumber(), getColumnNumber(), "Invalid value passed to special function!"); return new Real(exp(cast->getValue())); } throw InvalidTypeException(getLineNumber(), getColumnNumber(), OBJ_INTEGER | OBJ_REAL, arg1->getType(), 1); } if(id == SPF_EXP) { if(arg1->getType() == OBJ_INTEGER) { Integer* cast = static_cast<Integer*>(arg1.get()); return new Real(exp((double) cast->getValue())); } if(arg1->getType() == OBJ_REAL) { Real* cast = static_cast<Real*>(arg1.get()); return new Real(exp(cast->getValue())); } throw InvalidTypeException(getLineNumber(), getColumnNumber(), OBJ_INTEGER | OBJ_REAL, arg1->getType(), 1); } if(id == SPF_LN) { if(arg1->getType() == OBJ_INTEGER) { Integer* cast = static_cast<Integer*>(arg1.get()); return new Real(log((double) cast->getValue())); } if(arg1->getType() == OBJ_REAL) { Real* cast = static_cast<Real*>(arg1.get()); return new Real(log(cast->getValue())); } throw InvalidTypeException(getLineNumber(), getColumnNumber(), OBJ_INTEGER | OBJ_REAL, arg1->getType(), 1); } if(id == SPF_LG) { if(arg1->getType() == OBJ_INTEGER) { Integer* cast = static_cast<Integer*>(arg1.get()); return new Real(log10((double) cast->getValue())); } if(arg1->getType() == OBJ_REAL) { Real* cast = static_cast<Real*>(arg1.get()); return new Real(log10(cast->getValue())); } throw InvalidTypeException(getLineNumber(), getColumnNumber(), OBJ_INTEGER | OBJ_REAL, arg1->getType(), 1); } throw Excep(getLineNumber(), getColumnNumber(), "Invalid special function!"); }
Foam::dimensionSet Foam::equationReader::getDimsSrcEquationCircRefDetect ( const equationReader * eqnReader, const label equationIndex, const label equationOperationIndex, const label maxStoreIndex, const label storageOffset ) const { const equation& eqn(operator[](equationIndex)); equationOperation& eqOp(eqn[equationOperationIndex]); label zeroSourceIndex = mag(eqOp.sourceIndex()) - 1; // Check for circular references dependents_.setSize(dependents_.size() + 1); dependents_[dependents_.size() - 1] = equationIndex; forAll(dependents_, i) { if (dependents_[i] == zeroSourceIndex) { // Circular reference detected string dependencies; for (label j(i); j < dependents_.size(); j++) { dependencies.append ( operator[](dependents_[j]).name() ); dependencies.append("-->"); } dependencies.append(operator[](dependents_[i]).name()); FatalErrorIn ( "equationReader::getDimsSrcEquationCircRefDetect" ) << "Circular reference detected when evaluating " << "the equation for " << eqn.name() << ", given by:" << token::NL << token::TAB << eqn.rawText() << token::NL << "The circular " << "dependency is:" << token::NL << token::TAB << dependencies << abort(FatalError); } } // Launch the reportEmbeddedDispatchFunction: // if (debug) // { // reportEmbeddedDispatchEnabled; // // or: Info << "Embedded equation dispatch." << endl; // } // else // { // reportEmbeddedDispatchDisabled(); // // does nothing // } (*this.*reportEmbeddedDispatchFunction_)(); // Call the associated evaluateDimensions function pointer - has the same // effect as this: // // const equation& eqn(operator[](zeroSourceIndex)); // if (eqn.changeDimensions()) // { // evaluateDimsDisabled(zeroSourceIndex, maxStoreIndex + 1); // // which in turn does: return eqn.overrideDimensions(); // } // else // { // evaluadeDimsEnabled(zeroSourceIndex, maxStoreIndex + 1); // // which in turn does: // // return internalEvaluateDimensions // // (zeroSourceIndex, maxStoreIndex + 1); // } dimensionSet returnMe ( (*this.*evaluateDimsFunctions_[zeroSourceIndex]) (zeroSourceIndex, maxStoreIndex + 1) ); // Launch the reportEmbeddedReturnFunction: // if (debug) // { // reportEmbeddedReturnEnabled; // // or: Info << "Return from equation equation." << endl; // } // else // { // reportEmbeddedReturnDisabled(); // // does nothing // } (*this.*reportEmbeddedReturnFunction_)(); //Move one level back up on the dependents_ list if (dependents_.size()) { dependents_.setSize(dependents_.size() - 1); } return returnMe; }