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; }
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(); }
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; }
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; }
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); } }
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; }