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