예제 #1
0
ASTNode* XQFunctionCoercion::staticResolution(StaticContext *context)
{
  XPath2MemoryManager *mm = context->getMemoryManager();

  _exprType->staticResolution(context);
  _expr = _expr->staticResolution(context);

  bool isExact;
  _exprType->getStaticType(_treatType, context, isExact, this);

  const SequenceType::ItemType *type = _exprType->getItemType();
  if(!type || type->getItemTestType() != SequenceType::ItemType::TEST_FUNCTION ||
     type->getReturnType() == 0)
    return substitute(_expr);

  // Construct an XQInlineFunction that will convert a function reference
  // stored in a variable to the correct type, and will throw type errors
  // if it isn't the correct type

  // Simultaneously create the XQInlineFunction parameter spec and the
  // XQFunctionDeref argument list
  ArgumentSpecs *paramList = new (mm) ArgumentSpecs(XQillaAllocator<ArgumentSpec*>(mm));
  VectorOfASTNodes *argList = new (mm) VectorOfASTNodes(XQillaAllocator<ASTNode*>(mm));

  VectorOfSequenceTypes *argTypes = type->getArgumentTypes();
  for(VectorOfSequenceTypes::iterator i = argTypes->begin(); i != argTypes->end(); ++i) {
    const XMLCh *argName = context->allocateTempVarName(argVarPrefix);

    ArgumentSpec *argSpec = new (mm) ArgumentSpec(argName, *i, mm);
    argSpec->setLocationInfo(*i);
    paramList->push_back(argSpec);
    
    XQVariable *argVar = new (mm) XQVariable(0, argName, mm);
    argVar->setLocationInfo(this);
    argList->push_back(argVar);
  }

  XQVariable *funcVar = new (mm) XQVariable(0, funcVarName, mm);
  funcVar->setLocationInfo(this);

  XQFunctionDeref *body = new (mm) XQFunctionDeref(funcVar, argList, mm);
  body->setLocationInfo(this);

  FunctionSignature *signature = new (mm) FunctionSignature(paramList, type->getReturnType(), mm);

  XQUserFunction *func = new (mm) XQUserFunction(0, signature, body, false, mm);
  func->setLocationInfo(this);

  _funcConvert = new (mm) XQInlineFunction(func, mm);
  _funcConvert->setLocationInfo(this);

  _funcConvert = _funcConvert->staticResolution(context);

  return this;
}
예제 #2
0
void ImpliedSchemaGenerator::generateSubstring(ImpliedSchemaNode::Type type, VectorOfASTNodes &args, PathResult &result,
	ASTNode *item)
{
	if(args.size() > 2) {
		// TBD case/diacritic insensitive collation? - jpcs

		// Mark the collation argument
		generate(args[2]).markSubtreeValue();
	}

	PathResult ret = generate(args[0]);
	generate(args[1]).markSubtreeValue();

	XPath2MemoryManager *mm = mm_;
	for(QueryPathNode::Vector::iterator it = ret.returnPaths.begin(); it != ret.returnPaths.end(); ++it) {
		ImpliedSchemaNode *newChild = (ImpliedSchemaNode*)(*it)->appendChild(new (mm)
			ImpliedSchemaNode(type, /*generalComp*/false, Syntax::STRING, args[1], mm));
		result.join(newChild);
	}
	addPaths(item, result.returnPaths, mm_);

	// We don't want to return any ImpliedSchemaNodes with a type
	// other than child, attribute, or descendant.
	result.returnPaths.clear();
}
예제 #3
0
ASTNode *FunctionRefImpl::createInstance(const FuncFactory *factory, const FunctionSignature *signature,
                                         XPath2MemoryManager *mm, const LocationInfo *location)
{
  VectorOfASTNodes newArgs = VectorOfASTNodes(XQillaAllocator<ASTNode*>(mm));
  if(signature->argSpecs) {
    ArgumentSpecs::const_iterator argsIt = signature->argSpecs->begin();
    for(; argsIt != signature->argSpecs->end(); ++argsIt) {
      assert((*argsIt)->getName() != 0);
      XQVariable *var = new (mm) XQVariable((*argsIt)->getURI(), (*argsIt)->getName(), mm);
      var->setLocationInfo(location);
      newArgs.push_back(var);
    }
  }

  ASTNode *instance = factory->createInstance(newArgs, mm);
  instance->setLocationInfo(location);
  return instance;
}
예제 #4
0
ASTNode *FunctionRefImpl::createInstance(const XMLCh *uri, const XMLCh *name, unsigned int numArgs,
                                         StaticContext *context, const LocationInfo *location,
                                         FunctionSignature *&signature)
{
  XPath2MemoryManager *mm = context->getMemoryManager();

  VectorOfASTNodes newArgs = VectorOfASTNodes(XQillaAllocator<ASTNode*>(mm));
  for(unsigned int i = 0; i < numArgs; ++i) {
    newArgs.push_back(0); // Dummy argument
  }

  ASTNode *result = context->lookUpFunction(uri, name, newArgs, location);
  if(!result) return 0;

  switch(result->getType()) {
  case ASTNode::FUNCTION:
  case ASTNode::USER_FUNCTION: {
    XQFunction *function = (XQFunction*)result;
    function->parseSignature(context);
    signature = new (mm) FunctionSignature(function->getSignature(), mm);

    if(signature->argSpecs) {
      // Fill in the arguments with XQVariable objects
      ArgumentSpecs::const_iterator argsIt = signature->argSpecs->begin();
      VectorOfASTNodes &args = const_cast<VectorOfASTNodes&>(function->getArguments());
      for(VectorOfASTNodes::iterator i = args.begin(); i != args.end(); ++i, ++argsIt) {
        (*i) = new (mm) XQVariable((*argsIt)->getURI(), (*argsIt)->getName(), mm);
        (*i)->setLocationInfo(location);
      }
    }

    break;
  }
  case ASTNode::CAST_AS: {
    XQCastAs *cast = (XQCastAs*)result;

    // Fill in the argument with an XQVariable object
    XQVariable *var = new (mm) XQVariable(0, constructorArgName, mm);
    var->setLocationInfo(location);
    cast->setExpression(var);

    // Create a signature for the constructor function
    SequenceType *argType = new (mm) SequenceType(SchemaSymbols::fgURI_SCHEMAFORSCHEMA,
                                                  AnyAtomicType::fgDT_ANYATOMICTYPE,
                                                  SequenceType::QUESTION_MARK, mm);
    argType->setLocationInfo(location);

    ArgumentSpec *arg = new (mm) ArgumentSpec(constructorArgName, argType, mm);
    arg->setLocationInfo(location);

    ArgumentSpecs *args = new (mm) ArgumentSpecs(XQillaAllocator<ArgumentSpec*>(mm));
    args->push_back(arg);

    signature = new (mm) FunctionSignature(args, cast->getSequenceType(), mm);
    signature->staticResolution(context);
    break;
  }
  default:
    assert(false);
    break;
  }

  return result;
}
예제 #5
0
void XQUserFunction::staticResolutionStage1(StaticContext *context)
{
  XPath2MemoryManager *mm = context->getMemoryManager();

  resolveName(context);

  if(name_ != 0 && !isTemplate_ && !delayed_) {
    if(XPath2Utils::equals(uri_, XMLUni::fgXMLURIName) ||
       XPath2Utils::equals(uri_, SchemaSymbols::fgURI_SCHEMAFORSCHEMA) ||
       XPath2Utils::equals(uri_, SchemaSymbols::fgURI_XSI) ||
       XPath2Utils::equals(uri_, XQFunction::XMLChFunctionURI) ||
       XPath2Utils::equals(uri_, SchemaSymbols::fgURI_SCHEMAFORSCHEMA)) {
      XQThrow(FunctionException, X("XQUserFunction::staticResolutionStage1"),
              X("A user defined function must not be in the namespaces xml, xsd, xsi, fn or xdt [err:XQST0045]"));
    }
    else if(uri_ == 0 || *uri_ == 0)
      XQThrow(FunctionException, X("XQUserFunction::staticResolutionStage1"),
              X("A user defined function must be defined in a namespace [err:XQST0060]"));
  }

  // Check for the implementation of an external function
  if(body_ == NULL) {
    exFunc_ = context->lookUpExternalFunction(uri_, name_, minArgs_);

    if(exFunc_ == NULL) {
      XMLBuffer buf;
      buf.set(X("External function '{"));
      buf.append(uri_);
      buf.append(X("}"));
      buf.append(name_);
      buf.append(X("' with "));
      XMLCh szNumBuff[20];
      XMLString::binToText((unsigned int)minArgs_, szNumBuff, 19, 10);
      buf.append(szNumBuff);
      buf.append(X(" argument(s) has not been bound to an implementation"));
      XQThrow(FunctionException, X("XQUserFunction::staticResolutionStage1"), buf.getRawBuffer());
    }
  }

  signature_->staticResolution(context);

  // Resolve the mode names
  if(modes_) {
    if(modes_->empty()) {
      XQThrow(StaticErrorException, X("XQUserFunction::staticResolution"),
              X("At least one mode must be specified for a template [err:XTSE0550]"));
    }

    ModeList::iterator it, it2;
    for(it = modes_->begin(); it != modes_->end(); ++it) {
      (*it)->staticResolution(context);

      // Check for "#all" with other values
      if((*it)->getState() == Mode::ALL && modes_->size() != 1) {
        XQThrow3(StaticErrorException, X("XQUserFunction::staticResolution"),
                 X("The mode #all must not be specified in addition to other modes [err:XTSE0550]"), *it);
      }

      // Check for duplicate modes
      it2 = it;
      for(++it2; it2 != modes_->end(); ++it2) {
        if((*it)->getState() == (*it2)->getState() &&
           XPath2Utils::equals((*it)->getName(), (*it2)->getName()) &&
           XPath2Utils::equals((*it)->getURI(), (*it2)->getURI())) {
          XMLBuffer buf;
          buf.append(X("The mode {"));
          buf.append((*it)->getURI());
          buf.append(X("}"));
          buf.append((*it)->getName());
          buf.append(X(" has been specified more than once [err:XTSE0550]"));
          XQThrow3(StaticErrorException, X("XQUserFunction::staticResolution"), buf.getRawBuffer(), *it2);
        }
      }
    }
  }

  // Set up a default StaticType and StaticAnalysis
  if(signature_->returnType) {
    if(body_ != NULL) {
      body_ = signature_->returnType->convertFunctionArg(body_, context, /*numericfunction*/false, signature_->returnType);
    }

    bool isPrimitive;
    signature_->returnType->getStaticType(src_.getStaticType(), context, isPrimitive, signature_->returnType);
  }
  else {
    // Default type is item()*
    src_.getStaticType() = StaticType(StaticType::ITEM_TYPE, 0, StaticType::UNLIMITED);
  }

  if(signature_->updating == FunctionSignature::OP_TRUE) {
    src_.updating(true);
  }

  // TBD What about the other parts of the StaticAnalysis - jpcs
  src_.forceNoFolding(true);

  if(pattern_ != 0 && !pattern_->empty()) {
    // Set the pattern's initial static type to NODE_TYPE
    VectorOfASTNodes::iterator patIt = pattern_->begin();
    for(; patIt != pattern_->end(); ++patIt) {
      const_cast<StaticAnalysis&>((*patIt)->getStaticAnalysis()).getStaticType() = StaticType(StaticType::NODE_TYPE, 0, StaticType::UNLIMITED);
    }
  }

  if(isTemplate_) {
    // Build an instance of the template for us to call
    VectorOfASTNodes newArgs = VectorOfASTNodes(XQillaAllocator<ASTNode*>(mm));

    if(signature_->argSpecs != 0) {
      ArgumentSpecs::const_iterator argIt;
      for(argIt = signature_->argSpecs->begin(); argIt != signature_->argSpecs->end(); ++argIt) {
        XQVariable *argVar = new (mm) XQVariable((*argIt)->getURI(), (*argIt)->getName(), mm);
        argVar->setLocationInfo(*argIt);
        newArgs.push_back(argVar);
      }
    }

    templateInstance_ = createInstance(newArgs, mm);
    templateInstance_->setLocationInfo(this);
  }
}
예제 #6
0
파일: XQSequence.cpp 프로젝트: kanbang/Colt
ASTNode *XQSequence::staticTypingImpl(StaticContext *context)
{
  _src.clear();

  bool doneOne = false;
  bool possiblyUpdating = true;
  bool nestedSeq = false;
  VectorOfASTNodes::iterator i = _astNodes.begin();

  if(i == _astNodes.end()) {
    _src.possiblyUpdating(true);
  }

  for(; i != _astNodes.end(); ++i) {
    if(_src.isUpdating()) {
      if(!(*i)->getStaticAnalysis().isUpdating() &&
         !(*i)->getStaticAnalysis().isPossiblyUpdating())
        XQThrow(StaticErrorException, X("XQSequence::staticTyping"),
                X("Mixed updating and non-updating operands [err:XUST0001]"));
    }
    else {
      if((*i)->getStaticAnalysis().isUpdating() && !possiblyUpdating)
        XQThrow(StaticErrorException, X("XQSequence::staticTyping"),
                X("Mixed updating and non-updating operands [err:XUST0001]"));
    }

    if(possiblyUpdating)
      possiblyUpdating = (*i)->getStaticAnalysis().isPossiblyUpdating();

    if(!doneOne) {
      doneOne = true;
      _src.getStaticType() = (*i)->getStaticAnalysis().getStaticType();
    } else {
      _src.getStaticType().typeConcat((*i)->getStaticAnalysis().getStaticType());
    }

    if((*i)->getType() == SEQUENCE)
      nestedSeq = true;

    _src.add((*i)->getStaticAnalysis());
  }

  if(context && nestedSeq) {
    XPath2MemoryManager *mm = context->getMemoryManager();
    VectorOfASTNodes newArgs = VectorOfASTNodes(XQillaAllocator<ASTNode*>(mm));
    for(i = _astNodes.begin(); i != _astNodes.end(); ++i) {
      if((*i)->getType() == SEQUENCE) {
        XQSequence *arg = (XQSequence*)*i;
        for(VectorOfASTNodes::iterator j = arg->_astNodes.begin(); j != arg->_astNodes.end(); ++j) {
          newArgs.push_back(*j);
        }
      }
      else {
        newArgs.push_back(*i);
      }
    }
    _astNodes = newArgs;
  }

  // Dissolve ourselves if we have only one child
  if(context && _astNodes.size() == 1) {
    return _astNodes.front();
  }
  return this;
}