Beispiel #1
0
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;
}
Beispiel #2
0
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);
}
Beispiel #3
0
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();
  }
}