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_COMPILER_SCRIPT_EXPRS
18 #define ZORBA_COMPILER_SCRIPT_EXPRS
19 
20 #include <vector>
21 
22 #include "compiler/expression/expr_base.h"
23 
24 
25 namespace zorba
26 {
27 
28 class expr_visitor;
29 class var_expr;
30 class exit_catcher_expr;
31 
32 
33 /***************************************************************************//**
34 
35   MainModule := Prolog Program
36 
37   Program := StatementsAndOptionalExpr
38 
39   StatementsAndOptionalExpr := Statements Expr?
40 
41   StatementsAndExpr := Statements Expr
42 
43   Statements := Statement*
44 
45   Statement := ApplyStatement      |
46                VarDeclStatement    |
47                AssignStatement     |
48                WhileStatement      |
49                BreakStatement      |
50                ContinueStatement   |
51                ExitStatement       |
52 
53                BlockStatement      |
54                FLWORStatement      |
55                IfStatement         |
56                SwitchStatement     |
57                TypeSwitchStatement |
58                TryCatchStatement
59 
60   Expr := ExprSingle ("," ExprSingle)*
61 
62   ExprSingle := FLWORExpr      |
63                 IfExpr         |
64                 SwitchExpr     |
65                 TypeSwitchExpr |
66                 TryCatchExpr   |
67 
68                 ExprSimple
69 
70   ExprSimple := QuantifiedExpr |
71                 OrExpr         |   <-- this may end up being a BlockExpr
72                 InsertExpr     |
73                 DeleteExpr     |
74                 ReplaceExpr    |
75                 RenameExpr     |
76                 TransformExpr
77 
78   BlockStatement := "{" Statements "}"
79 
80   BlockExpr := "{" StatementsAndExpr "}"
81 
82   Semantics:
83 
84   The runtime implementation of block expr is very permissive: it evaluates each
85   operand from left to right and returns its result (if any). The implementation
86   does not care if the result of an operand is XDM or PUL or both; it simply
87   propagates the result to the consumer iterator.
88 
89   However, the translator makes sure that a block expr does not mix updating
90   and sequential expressions. (there is one exception to this rule; see below.)
91 
92   The translator is still more permissive than the grammar. It allows a block
93   expr to mix simple and sequential exprs, or simple and updating exprs. In
94   contrast, the grammar allows only the last operand to be simple; all the other
95   operands must be sequential or vacuous.
96 
97   EXCEPTION: At the top level, a Program consists of 0 or more statements
98   followed by an expr, which may be updating. In the case of a "normal" program,
99   we can wrap this expr with an apply_expr and model the Program as a block
100   expr. However, this does not work in the case of eval-updating. The solution
101   is to pass a special flag to the constructor of block expr to allow the last
102   operand to be an updating expr.
103 ********************************************************************************/
104 class block_expr : public expr
105 {
106   friend class ExprManager;
107   friend class ExprIterator;
108   friend class expr;
109 
110 protected:
111   std::vector<expr*> theArgs;
112 
113 protected:
114   block_expr(
115       CompilerCB* ccb,
116       static_context* sctx,
117       const QueryLoc& loc,
118       bool allowLastUpdating,
119       std::vector<expr*>& seq,
120       std::vector<var_expr*>* assignedVars);
121 
122 public:
123   ~block_expr();
124 
125   void add_at(csize pos, expr* arg);
126 
size()127   csize size() const { return theArgs.size(); }
128 
129   const expr* operator[](csize i) const { return theArgs[i]; }
130 
131   expr* operator[](csize i) { return theArgs[i]; }
132 
133   expr* cloneImpl(substitution_t& s) const;
134 
135   void accept(expr_visitor&);
136 
137   std::ostream& put(std::ostream&) const;
138 
139 private:
140   void compute_scripting_kind();
141 
142   void compute_scripting_kind2(
143       std::vector<var_expr*>* assignedVars,
144       bool allowLastUpdating) ;
145 };
146 
147 
148 /*******************************************************************************
149   ApplyStatement ::= ExprSimple ";"
150 ********************************************************************************/
151 class apply_expr : public expr
152 {
153   friend class ExprManager;
154   friend class ExprIterator;
155   friend class expr;
156 
157 private:
158   expr * theExpr;
159   bool   theDiscardXDM;
160 
161 protected:
162   apply_expr(
163       CompilerCB* ccb,
164       static_context* sctx,
165       const QueryLoc& loc,
166       expr* inExpr,
167       bool discardXDM);
168 
169 public:
get_expr()170   expr* get_expr() const { return theExpr;}
171 
discardsXDM()172   bool discardsXDM() const { return theDiscardXDM; }
173 
174   void compute_scripting_kind();
175 
176   expr* cloneImpl(substitution_t& s) const;
177 
178   void accept(expr_visitor&);
179 
180   std::ostream& put(std::ostream&) const;
181 };
182 
183 
184 /*******************************************************************************
185 
186   For Global Var:
187   ----------------
188 
189   AnnotatedDecl ::= "declare" Annotation* (VarDecl | FunctionDecl)
190 
191   Annotation ::= "%" EQName ("(" Literal ("," Literal)* ")")?
192 
193   VarDecl ::= "variable" "$" VarName TypeDeclaration?
194               ((":=" VarValue) | ("external" (":=" VarDefaultValue)?))
195 
196   For Local Var:
197   --------------
198 
199   VarDeclExpr ::= ("local" Annotation*)? "variable" "$" VarName TypeDeclaration?
200                   (":=" ExprSingle)?
201 
202   var_decl_expr is used to declare block-local and prolog variables (including
203   the context item, if it is declared in the prolog). During runtime, the
204   associated iterator creates in the local dynamic context a binding between
205   the variable id and the variable value. If the declaration includes an
206   initializing expr, the iterator computes the initExpr and stores the resulting
207   value inside this binding.
208 
209   Note: the init expr must be non-updating. For global vars, it must also be
210   non-sequential.
211 ********************************************************************************/
212 class var_decl_expr : public expr
213 {
214   friend class ExprManager;
215   friend class ExprIterator;
216   friend class expr;
217 
218 protected:
219   var_expr * theVarExpr;
220   expr     * theInitExpr;
221 
222 protected:
223   var_decl_expr(
224       CompilerCB* ccb,
225       static_context* sctx,
226       const QueryLoc& loc,
227       var_expr* varExpr,
228       expr* initExpr);
229 
230 public:
231   ~var_decl_expr();
232 
get_var_expr()233   var_expr* get_var_expr() const { return theVarExpr; }
234 
get_init_expr()235   expr* get_init_expr() const { return theInitExpr; }
236 
237   void compute_scripting_kind();
238 
239   expr* cloneImpl(substitution_t& s) const;
240 
241   void accept(expr_visitor&);
242 
243   std::ostream& put(std::ostream&) const;
244 };
245 
246 
247 /*******************************************************************************
248 
249   AssignStatement ::= "$" VarName ":=" ExprSingle ";"
250 
251   The RHS of the assignment must be a non-updating expr.
252 
253   var_set_expr is used to assign a value to a prolog or block-local var. During
254   runtime, the function computes theExpr and stores the resulting value inside
255   the appropriate dynamic ctx (global or local), at the location that is identified
256   by the variable id.
257 ********************************************************************************/
258 class var_set_expr : public expr
259 {
260   friend class ExprManager;
261   friend class ExprIterator;
262   friend class expr;
263 
264 protected:
265   var_expr * theVarExpr;
266   expr     * theExpr;
267 
268 protected:
269   var_set_expr(
270       CompilerCB* ccb,
271       static_context* sctx,
272       const QueryLoc& loc,
273       var_expr* varExpr,
274       expr* setExpr);
275 
276 public:
277   ~var_set_expr();
278 
get_var_expr()279   var_expr* get_var_expr() const { return theVarExpr; }
280 
get_expr()281   expr* get_expr() const { return theExpr; }
282 
283   void compute_scripting_kind();
284 
285   expr* cloneImpl(substitution_t& s) const;
286 
287   void accept(expr_visitor&);
288 
289   std::ostream& put(std::ostream&) const;
290 };
291 
292 
293 /*******************************************************************************
294   ExitExpr ::= "exit" "with" ExprSingle
295 ********************************************************************************/
296 class exit_expr : public expr
297 {
298   friend class ExprManager;
299   friend class ExprIterator;
300   friend class expr;
301 
302 private:
303   expr               * theExpr;
304 
305   exit_catcher_expr  * theCatcherExpr;
306 
307 protected:
308   exit_expr(
309       CompilerCB* ccb,
310       static_context* sctx,
311       const QueryLoc& loc,
312       expr* inExpr);
313 
314 public:
315   ~exit_expr();
316 
get_expr()317   expr* get_expr() const { return theExpr; }
318 
setCatcherExpr(exit_catcher_expr * e)319   void setCatcherExpr(exit_catcher_expr* e) { theCatcherExpr = e; }
320 
321   void compute_scripting_kind();
322 
323   expr* cloneImpl(substitution_t& s) const;
324 
325   void accept(expr_visitor&);
326 
327   std::ostream& put(std::ostream&) const;
328 };
329 
330 
331 /*******************************************************************************
332   A "helper" expr to catch the exception thrown by an exit_expr that appears
333   inside a UDF. It is placed between the return-type-checking expr(s) at the
334   top of the UDF body and the effective UDF body.
335 
336   theExpr:
337   --------
338   The child expr of "this" exit_catcher_expr (i.e., the effective UDF body).
339 
340   theExitExprs:
341   -------------
342   All the exit_exprs that appear in the body of the udf.
343 ********************************************************************************/
344 class exit_catcher_expr : public expr
345 {
346   friend class ExprManager;
347   friend class ExprIterator;
348   friend class expr;
349 
350 private:
351   expr             * theExpr;
352 
353   std::vector<expr*> theExitExprs;
354 
355 protected:
356   exit_catcher_expr(
357       CompilerCB* ccb,
358       static_context* sctx,
359       const QueryLoc& loc,
360       expr* inExpr,
361       std::vector<expr*>& exitExprs);
362 
363 public:
364   ~exit_catcher_expr();
365 
get_expr()366   expr* get_expr() const { return theExpr; }
367 
exitExprsBegin()368   std::vector<expr*>::const_iterator exitExprsBegin() const
369   {
370     return theExitExprs.begin();
371   }
372 
exitExprsEnd()373   std::vector<expr*>::const_iterator exitExprsEnd() const
374   {
375     return theExitExprs.end();
376   }
377 
378   void removeExitExpr(const expr* exitExpr);
379 
380   void compute_scripting_kind();
381 
382   expr* cloneImpl(substitution_t& s) const;
383 
384   void accept(expr_visitor&);
385 
386   std::ostream& put(std::ostream&) const;
387 };
388 
389 
390 /*******************************************************************************
391 
392 ********************************************************************************/
393 class flowctl_expr : public expr
394 {
395   friend class ExprManager;
396   friend class ExprIterator;
397   friend class expr;
398 
399 public:
400   enum action { BREAK, CONTINUE };
401 
402 protected:
403   enum action theAction;
404 
405 protected:
406   flowctl_expr(CompilerCB* ccb, static_context* sctx, const QueryLoc& loc, enum action action);
407 
408 public:
get_action()409   enum action get_action() const { return theAction; }
410 
411   expr* cloneImpl(substitution_t& s) const;
412 
413   void compute_scripting_kind();
414 
415   void accept(expr_visitor&);
416 
417   std::ostream& put(std::ostream&) const;
418 };
419 
420 
421 /*******************************************************************************
422   WhileExpr ::= "while" "(" Expr ")" Statement
423 
424   theBody : It is a block_expr, whose 1st child is the following expr:
425             if (cond_expr) then () else break
426             The subsequent children are what it generated by the Statement.
427 ********************************************************************************/
428 class while_expr : public expr
429 {
430   friend class ExprManager;
431   friend class ExprIterator;
432   friend class expr;
433 
434 protected:
435   expr* theBody;
436 
437 protected:
438   while_expr(CompilerCB* ccb, static_context* sctx, const QueryLoc& loc, expr* body);
439 
440 public:
get_body()441   expr* get_body() const { return theBody; }
442 
443   void compute_scripting_kind();
444 
445   expr* cloneImpl(substitution_t& s) const;
446 
447   void accept(expr_visitor&);
448 
449   std::ostream& put(std::ostream&) const;
450 };
451 
452 
453 
454 }
455 #endif
456 
457 /*
458  * Local variables:
459  * mode: c++
460  * End:
461  */
462 /* vim:set et sw=2 ts=2: */
463