ASTNode *DbXmlStaticTyper::optimizeDbXmlPredicate(DbXmlPredicate *item) { item->setExpression(optimize(item->getExpression())); AutoContextItemTypeReset contextTypeReset(context_); VariableTypeStore* varStore = context_ ? context_->getVariableTypeStore() : 0; if(context_) { StaticAnalysis &varSrc = item->getVarSRC(); varSrc.getStaticType() = item->getExpression()->getStaticAnalysis().getStaticType(); varSrc.setProperties(StaticAnalysis::DOCORDER | StaticAnalysis::GROUPED | StaticAnalysis::PEER | StaticAnalysis::SUBTREE | StaticAnalysis::SAMEDOC | StaticAnalysis::ONENODE | StaticAnalysis::SELF); if(item->getName() == 0) { context_->setContextItemType(varSrc.getStaticType()); } else { varStore->addLogicalBlockScope(); varStore->declareVar(item->getURI(), item->getName(), varSrc); } } item->setPredicate(optimize(const_cast<ASTNode *>(item->getPredicate()))); if(context_ && item->getName() != 0) { varStore->removeScope(); } return item; }
void XQQuery::staticTyping(StaticTyper *styper) { StaticContext *context = m_context; StaticTyper defaultTyper; if(styper == 0) styper = &defaultTyper; VariableTypeStore* varStore = context->getVariableTypeStore(); // Static type the imported modules (again) ImportedModules::const_iterator modIt; for(modIt = m_importedModules.begin(); modIt != m_importedModules.end(); ++modIt) { (*modIt)->staticTyping(styper); } // Define types for the imported variables for(modIt = m_importedModules.begin(); modIt != m_importedModules.end(); ++modIt) { for(GlobalVariables::const_iterator varIt = (*modIt)->m_userDefVars.begin(); varIt != (*modIt)->m_userDefVars.end(); ++varIt) { varStore->declareGlobalVar((*varIt)->getVariableURI(), (*varIt)->getVariableLocalName(), (*varIt)->getStaticAnalysis()); } } // Run staticTyping on the global variables if(!m_userDefVars.empty()) { // declare all the global variables with a special StaticAnalysis, in order to recognize 'variable is defined // later' errors instead of more generic 'variable not found'. In order to catch references to not yet defined // variables (but when no recursion happens) we also create a scope where we undefine the rest of the variables (once // we enter in a function call, the scope will disappear and the forward references to the global variables will // appear). StaticAnalysis forwardRef(context->getMemoryManager()); forwardRef.setProperties(StaticAnalysis::FORWARDREF); StaticAnalysis undefinedVar(context->getMemoryManager()); undefinedVar.setProperties(StaticAnalysis::UNDEFINEDVAR); GlobalVariables::iterator itVar, itVar2; for(itVar = m_userDefVars.begin(); itVar != m_userDefVars.end(); ++itVar) { varStore->declareGlobalVar((*itVar)->getVariableURI(), (*itVar)->getVariableLocalName(), forwardRef); } for(itVar = m_userDefVars.begin(); itVar != m_userDefVars.end(); ++itVar) { varStore->addLogicalBlockScope(); for(itVar2 = itVar; itVar2 != m_userDefVars.end(); ++itVar2) { varStore->declareVar((*itVar2)->getVariableURI(), (*itVar2)->getVariableLocalName(), undefinedVar); } (*itVar)->staticTyping(context, styper); varStore->removeScope(); } } // Run staticTyping on the user defined functions, // which calculates a better type for them UserFunctions::iterator i, j; for(i = m_userDefFns.begin(); i != m_userDefFns.end(); ++i) { for(j = m_userDefFns.begin(); j != m_userDefFns.end(); ++j) { (*j)->resetStaticTypingOnce(); } (*i)->staticTypingOnce(context, styper); } // Run staticTyping on the query body if(m_query) m_query = m_query->staticTyping(context, styper); }
void XQUserFunction::staticTyping(StaticContext *context, StaticTyper *styper) { // Nothing more to do for external functions if(body_ == NULL) return; if(signature_->updating == FunctionSignature::OP_TRUE && signature_->returnType != NULL) { XQThrow(StaticErrorException, X("XQUserFunction::staticTyping"), X("It is a static error for an updating function to declare a return type [err:XUST0028]")); } // Find user defined functions and templates that are referenced in our body, // and try to call staticTyping() on them before us. if(context) staticTypeFunctionCalls(body_, context, styper); bool ciTypeSet = false; StaticType ciType = StaticType(); if(pattern_ != NULL) { VectorOfASTNodes::iterator patIt = pattern_->begin(); for(; patIt != pattern_->end(); ++patIt) { (*patIt) = (*patIt)->staticTyping(context, styper); if(!ciTypeSet) { ciTypeSet = true; ciType = (*patIt)->getStaticAnalysis().getStaticType(); } else ciType |= (*patIt)->getStaticAnalysis().getStaticType(); } if(ciTypeSet) { ciType.setCardinality(1, 1); } } if(isTemplate_ && name_ != 0) { // Named template ciTypeSet = true; ciType = StaticType::ITEM_TYPE; } // define the new variables in a new scope and assign them the proper values if(context) { VariableTypeStore *varStore = context->getVariableTypeStore(); if(isGlobal_) varStore->addLocalScope(); else varStore->addLogicalBlockScope(); // Declare the parameters if(signature_->argSpecs) { ArgumentSpecs::iterator it; for(it = signature_->argSpecs->begin(); it != signature_->argSpecs->end (); ++it) { varStore->declareVar((*it)->getURI(), (*it)->getName(), (*it)->getStaticAnalysis()); } } } { // Declare the context item AutoContextItemTypeReset contextTypeReset(context, ciType); body_ = body_->staticTyping(context, styper); } if(context) context->getVariableTypeStore()->removeScope(); if(signature_->updating == FunctionSignature::OP_TRUE) { if(!body_->getStaticAnalysis().isUpdating() && !body_->getStaticAnalysis().isPossiblyUpdating()) XQThrow(StaticErrorException, X("XQUserFunction::staticTyping"), X("It is a static error for the body expression of a user defined updating function " "not to be an updating expression [err:XUST0002]")); } else { if(body_->getStaticAnalysis().isUpdating()) { if(isTemplate_) { XQThrow(StaticErrorException, X("XQUserFunction::staticTyping"), X("It is a static error for the body expression of a template " "to be an updating expression [err:XUST0001]")); } else { XQThrow(StaticErrorException, X("XQUserFunction::staticTyping"), X("It is a static error for the body expression of a user defined function " "to be an updating expression [err:XUST0001]")); } } } // Remove the parameter variables from the stored StaticAnalysis src_.clear(); src_.copy(body_->getStaticAnalysis()); if(signature_->argSpecs) { for(ArgumentSpecs::iterator it = signature_->argSpecs->begin(); it != signature_->argSpecs->end (); ++it) { if(!src_.removeVariable((*it)->getURI(), (*it)->getName())) { // The parameter isn't used, so set it to null, so that we don't bother to evaluate it (*it)->setNotUsed(); } } } // Run staticTyping on the template instances if(templateInstance_ != 0 && context) { StaticAnalysis templateVarSrc(context->getMemoryManager()); templateVarSrc.getStaticType() = StaticType::ITEM_TYPE; VariableTypeStore *varStore = context->getVariableTypeStore(); varStore->addLogicalBlockScope(); if(signature_->argSpecs != 0) { ArgumentSpecs::const_iterator argIt; for(argIt = signature_->argSpecs->begin(); argIt != signature_->argSpecs->end(); ++argIt) { varStore->declareVar((*argIt)->getURI(), (*argIt)->getName(), templateVarSrc); } } // Turn off warnings here, since they are largely irrelevent to the user AutoMessageListenerReset reset(context); templateInstance_ = templateInstance_->staticTyping(context, styper); varStore->removeScope(); } }