1 /* 2 * Copyright 2006-2008 The FLWOR Foundation. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #pragma once 17 #ifndef ZORBA_FUNCTIONS_UDF 18 #define ZORBA_FUNCTIONS_UDF 19 20 #include "functions/function.h" 21 22 #include "compiler/expression/expr_base.h" 23 24 25 namespace zorba 26 { 27 28 namespace store 29 { 30 class Index; 31 typedef rchandle<Index> Index_t; 32 } 33 34 35 /******************************************************************************* 36 A udf with params $x1, $x2, ..., $xn and a body_expr is translated into a 37 flwor expr: 38 39 let $x1 := $x1_, $x2 := $x2_, ..., $xn := $xn_ 40 return body_expr 41 42 The internally generated vars $x1_, ..., $xn_ are not registered in any sctx, 43 but they are registered in the udf obj instead (theArgVars data member). 44 45 A call to a udf is translated the same way as a call to a built-in function, 46 i.e., an fo_expr is created that points to the udf obj and also has a vector 47 of pointers to the arg exprs appearing in the function call. 48 49 theLoc: 50 ------- 51 The query location where this udf is declared at. 52 53 theBodyExpr: 54 ------------ 55 The expr tree representing what this function is doing. It is the result of 56 translating the udf declaration (so for a udf with one or more params, it is 57 the flwor expr described above). Note: translation of udf declarations 58 includes normalization and optimization of the expr tree. 59 60 theArgVars: 61 ----------- 62 The internally generated arg vars (the $xi_ vars described above) 63 64 theScriptingKind: 65 ----------------- 66 The declared scripting kind of this udf. Notice that the getScriptingKind 67 method will return the declared kind if the body is NULL, but after the body 68 has been translated, it will return the kind of the body expr. 69 70 theIsLeaf: 71 ---------- 72 True if this udf does not invoke any other udfs 73 74 thePlan: 75 -------- 76 77 thePlanStateSize: 78 ----------------- 79 80 theArgVarsRefs: 81 --------------- 82 For each arg var, this vector stores the LetVarIterators that represent the 83 references to that var within the udf body. If there are more than one 84 references of an arg var, these references are "mutually exclusive", ie, 85 at most one of the references will actually be reached during each particular 86 execution of the body. 87 88 theCache: 89 --------- 90 Maps the arg values of an invocation to the result of that invocation. 91 If an invocation uses the same arg values as a previous invocation, the cached 92 result is simply returned without re-evaluating the udf. 93 94 theCacheResults: 95 ---------------- 96 Tells whether caching should be done for this udf or not. 97 98 theCacheComputed: 99 ----------------- 100 Tells whether theCacheResults has been computed already or not. 101 theCacheResults is computed by the computeResultCaching() method, which is 102 invoked during codegen every time a udf call is encountered. The same udf may 103 be invoked multiple times, but the computation of theCacheResults needs to 104 be done only once. So, during the 1st invcocation of computeResultCaching(), 105 theCacheComputed is set to true, and subsequent invocations are noops. 106 ********************************************************************************/ 107 class user_function : public function 108 { 109 public: 110 typedef std::vector<LetVarIter_t> ArgVarRefs; 111 112 private: 113 CompilerCB * theCCB; 114 115 QueryLoc theLoc; 116 117 unsigned short theScriptingKind; 118 119 expr* theBodyExpr; 120 std::vector<var_expr*> theArgVars; 121 122 std::vector<unsigned char> theIgnoresSortedNodes; 123 std::vector<unsigned char> theIgnoresDuplicateNodes; 124 std::vector<unsigned char> theMustCopyInputNodes; 125 std::vector<unsigned char> thePropagatesInputNodes; 126 127 bool theIsExiting; 128 bool theIsLeaf; 129 130 std::vector<user_function*> theMutuallyRecursiveUDFs; 131 std::vector<expr*> theRecursiveCalls; 132 133 bool theIsOptimized; 134 135 PlanIter_t thePlan; 136 uint32_t thePlanStateSize; 137 std::vector<ArgVarRefs> theArgVarsRefs; 138 139 store::Index_t theCache; 140 bool theCacheResults; 141 bool theCacheComputed; 142 143 public: 144 SERIALIZABLE_CLASS(user_function) 145 user_function(::zorba::serialization::Archiver& ar); 146 void serialize(::zorba::serialization::Archiver& ar); 147 148 public: 149 user_function( 150 const QueryLoc& loc, 151 const signature& sig, 152 expr* expr_body, 153 unsigned short scriptingKind, 154 CompilerCB* compilerCB); 155 156 virtual ~user_function(); 157 158 //xqtref_t getUDFReturnType(static_context* sctx) const; 159 getLoc()160 const QueryLoc& getLoc() const { return theLoc; } 161 isExiting()162 bool isExiting() const { return theIsExiting; } 163 setExiting(bool v)164 void setExiting(bool v) { theIsExiting = v; } 165 setLeaf(bool v)166 void setLeaf(bool v) { theIsLeaf = v; } 167 isLeaf()168 bool isLeaf() const { return theIsLeaf; } 169 170 void setBody(expr* body); 171 172 expr* getBody() const; 173 174 void setArgVars(std::vector<var_expr*>& args); 175 176 const std::vector<var_expr*>& getArgVars() const; 177 getArgVar(csize i)178 var_expr* getArgVar(csize i) const { return theArgVars[i]; } 179 180 void addMutuallyRecursiveUDFs( 181 const std::vector<user_function*>& udfs, 182 const std::vector<user_function*>::const_iterator& cycle); 183 184 void addRecursiveCall(expr* call); 185 getRecursiveCalls()186 const std::vector<expr*>& getRecursiveCalls() const { return theRecursiveCalls; } 187 188 bool isMutuallyRecursiveWith(const user_function* udf); 189 190 bool isRecursive() const; 191 setOptimized(bool v)192 void setOptimized(bool v) { theIsOptimized = v; } 193 isOptimized()194 bool isOptimized() const { return theIsOptimized; } 195 196 void optimize(); 197 198 PlanIter_t getPlan(uint32_t& planStateSize); 199 200 void invalidatePlan(); 201 202 PlanIter_t codegen( 203 CompilerCB* cb, 204 static_context* sctx, 205 const QueryLoc& loc, 206 std::vector<PlanIter_t>& argv, 207 expr& ann) const; 208 209 // The next 6 methods are virtual methods of class function, which are redefined here 210 211 unsigned short getScriptingKind() const; 212 213 bool accessesDynCtx() const; 214 215 bool mustCopyInputNodes(expr* fo, csize input) const; 216 217 bool propagatesInputNodes(expr* fo, csize input) const; 218 219 BoolAnnotationValue ignoresSortedNodes(expr* fo, csize input) const; 220 221 BoolAnnotationValue ignoresDuplicateNodes(expr* fo, csize input) const; 222 223 // Runtime-related methods 224 setPlaneStateSize(uint32_t size)225 void setPlaneStateSize(uint32_t size) { thePlanStateSize = size; } 226 227 const std::vector<ArgVarRefs>& getArgVarsRefs() const; 228 229 store::Index* getCache() const; 230 231 void setCache(store::Index* aCache); 232 233 bool cacheResults() const; 234 235 void computeResultCaching(XQueryDiagnostics* diag); 236 }; 237 238 239 } /* namespace zorba */ 240 #endif 241 242 /* 243 * Local variables: 244 * mode: c++ 245 * End: 246 */ 247 /* vim:set et sw=2 ts=2: */ 248