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