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 #include "stdafx.h"
17
18 #include <vector>
19
20 #include "compiler/expression/fo_expr.h"
21 #include "compiler/expression/expr_visitor.h"
22
23 #include "compiler/api/compilercb.h"
24
25 #include "context/static_context.h"
26
27 #include "functions/library.h"
28 #include "functions/function.h"
29 #include "functions/udf.h"
30
31 #include "diagnostics/assert.h"
32 #include "diagnostics/util_macros.h"
33 #include "diagnostics/xquery_diagnostics.h"
34
35 namespace zorba
36 {
37
38
accept(expr_visitor & v)39 void fo_expr::accept(expr_visitor& v)
40 {
41 if (v.begin_visit(*this))
42 {
43 accept_children(v);
44 }
45
46 v.end_visit(*this);
47 }
48
49
50
51 /*******************************************************************************
52 first-order expressions. Represents function invocations as well as:
53
54 OrExpr, AndExpr, ComparisonExpr, RangeExpr, AdditiveExpr, MultiplicativeExpr,
55 UnionExpr, and IntersectExceptExpr.
56 ********************************************************************************/
57
create_seq(CompilerCB * ccb,static_context * sctx,const QueryLoc & loc)58 fo_expr* fo_expr::create_seq(CompilerCB* ccb, static_context* sctx, const QueryLoc& loc)
59 {
60 function* f = BuiltinFunctionLibrary::getFunction(FunctionConsts::OP_CONCATENATE_N);
61
62 std::auto_ptr<fo_expr> fo(ccb->theEM->create_fo_expr(sctx, loc, f));
63
64 return fo.release();
65 }
66
67
fo_expr(CompilerCB * ccb,static_context * sctx,const QueryLoc & loc,const function * f)68 fo_expr::fo_expr(
69 CompilerCB* ccb,
70 static_context* sctx,
71 const QueryLoc& loc,
72 const function* f)
73 :
74 expr(ccb, sctx, loc, fo_expr_kind),
75 theFunction(const_cast<function*>(f))
76 {
77 // This method is private and it is to be used only by the clone method
78 assert(f != NULL);
79 theScriptingKind = VACUOUS_EXPR;
80 }
81
82
fo_expr(CompilerCB * ccb,static_context * sctx,const QueryLoc & loc,const function * f,expr * arg)83 fo_expr::fo_expr(
84 CompilerCB* ccb,
85 static_context* sctx,
86 const QueryLoc& loc,
87 const function* f,
88 expr* arg)
89 :
90 expr(ccb, sctx, loc, fo_expr_kind),
91 theFunction(const_cast<function*>(f))
92 {
93 assert(f != NULL);
94 theArgs.resize(1);
95 theArgs[0] = arg;
96
97 compute_scripting_kind();
98 }
99
100
fo_expr(CompilerCB * ccb,static_context * sctx,const QueryLoc & loc,const function * f,expr * arg1,expr * arg2)101 fo_expr::fo_expr(
102 CompilerCB* ccb,
103 static_context* sctx,
104 const QueryLoc& loc,
105 const function* f,
106 expr* arg1,
107 expr* arg2)
108 :
109 expr(ccb, sctx, loc, fo_expr_kind),
110 theFunction(const_cast<function*>(f))
111 {
112 assert(f != NULL);
113 theArgs.resize(2);
114 theArgs[0] = arg1;
115 theArgs[1] = arg2;
116
117 compute_scripting_kind();
118 }
119
120
fo_expr(CompilerCB * ccb,static_context * sctx,const QueryLoc & loc,const function * f,const std::vector<expr * > & args)121 fo_expr::fo_expr(
122 CompilerCB* ccb,
123 static_context* sctx,
124 const QueryLoc& loc,
125 const function* f,
126 const std::vector<expr*>& args)
127 :
128 expr(ccb, sctx, loc, fo_expr_kind),
129 theArgs(args),
130 theFunction(const_cast<function*>(f))
131 {
132 assert(f != NULL);
133 compute_scripting_kind();
134 }
135
136
get_signature() const137 const signature& fo_expr::get_signature() const
138 {
139 return theFunction->getSignature();
140 }
141
142
get_fname() const143 const store::Item* fo_expr::get_fname() const
144 {
145 return theFunction->getName();
146 }
147
148
add_arg(expr * e)149 void fo_expr::add_arg(expr* e)
150 {
151 theArgs.push_back(e);
152 compute_scripting_kind();
153 }
154
155
add_args(const std::vector<expr * > & args)156 void fo_expr::add_args(const std::vector<expr*>& args)
157 {
158 theArgs.insert(theArgs.end(), args.begin(), args.end());
159 compute_scripting_kind();
160 }
161
162
remove_arg(csize i)163 void fo_expr::remove_arg(csize i)
164 {
165 theArgs.erase(theArgs.begin() + i);
166 compute_scripting_kind();
167 }
168
169
compute_scripting_kind()170 void fo_expr::compute_scripting_kind()
171 {
172 const function* func = get_func();
173 csize numArgs = num_args();
174
175 switch (func->getKind())
176 {
177 case FunctionConsts::OP_CONCATENATE_N:
178 {
179 bool vacuous = true;
180
181 theScriptingKind = VACUOUS_EXPR;
182
183 for (csize i = 0; i < numArgs; ++i)
184 {
185 if (theArgs[i] == NULL)
186 continue;
187
188 short argKind = theArgs[i]->get_scripting_detail();
189
190 if (argKind == VACUOUS_EXPR)
191 continue;
192
193 vacuous = false;
194
195 if (!theSctx->is_feature_set(feature::scripting))
196 {
197 if (is_updating() && !(argKind & UPDATING_EXPR) && argKind != VACUOUS_EXPR)
198 {
199 RAISE_ERROR(err::XUST0001, theArgs[i]->get_loc(),
200 ERROR_PARAMS(ZED(XUST0001_CONCAT)));
201 }
202
203 if (i > 0 && !is_updating() && !is_vacuous() && (argKind & UPDATING_EXPR))
204 {
205 RAISE_ERROR(err::XUST0001, theArgs[i]->get_loc(),
206 ERROR_PARAMS(ZED(XUST0001_CONCAT)));
207 }
208 }
209
210 theScriptingKind |= argKind;
211 }
212
213 if (!vacuous)
214 theScriptingKind &= ~VACUOUS_EXPR;
215
216 if (theScriptingKind & UPDATING_EXPR)
217 theScriptingKind &= ~SIMPLE_EXPR;
218
219 if (is_sequential(theScriptingKind))
220 theScriptingKind &= ~SIMPLE_EXPR;
221
222 checkScriptingKind();
223
224 break;
225 }
226 case FunctionConsts::OP_HOIST_1:
227 case FunctionConsts::OP_UNHOIST_1:
228 {
229 theScriptingKind = theArgs[0]->get_scripting_detail();
230 break;
231 }
232 default:
233 {
234 theScriptingKind = func->getScriptingKind();
235
236 bool vacuous = (theScriptingKind == VACUOUS_EXPR);
237
238 for (csize i = 0; i < numArgs; ++i)
239 {
240 if (theArgs[i] == NULL)
241 continue;
242
243 expr* arg = theArgs[i];
244
245 if (arg->is_updating())
246 {
247 RAISE_ERROR(err::XUST0001, theArgs[i]->get_loc(),
248 ERROR_PARAMS(ZED(XUST0001_Generic)));
249 }
250
251 short argKind = arg->get_scripting_detail();
252
253 if (arg->is_sequential())
254 {
255 vacuous = false;
256
257 theScriptingKind |= argKind;
258 }
259 }
260
261 if (!vacuous)
262 theScriptingKind &= ~VACUOUS_EXPR;
263
264 if (theScriptingKind & UPDATING_EXPR)
265 theScriptingKind &= ~SIMPLE_EXPR;
266
267 if (is_sequential(theScriptingKind))
268 theScriptingKind &= ~SIMPLE_EXPR;
269
270 checkScriptingKind();
271 }
272 }
273 }
274
275
cloneImpl(substitution_t & subst) const276 expr* fo_expr::cloneImpl(substitution_t& subst) const
277 {
278 if (get_func()->getKind() == FunctionConsts::STATIC_COLLECTIONS_DML_COLLECTION_1)
279 {
280 expr::subst_iter_t i = subst.find(this);
281
282 if (i != subst.end())
283 return i->second;
284 }
285
286 std::auto_ptr<fo_expr> fo(theCCB->theEM->create_fo_expr(theSctx,
287 get_loc(),
288 get_func()));
289
290 for (csize i = 0; i < theArgs.size(); ++i)
291 fo->theArgs.push_back(theArgs[i]->clone(subst));
292
293 fo->theScriptingKind = theScriptingKind;
294
295 return fo.release();
296 }
297
298
299 }
300
301 /* vim:set et sw=2 ts=2: */
302