00001
00002
00003 #include "../ProgramUnit.h"
00004 #include "../Collection/List.h"
00005 #include "../Collection/RefDatabase.h"
00006 #include "../Expression/LambdaCallExpr.h"
00007 #include "../Expression/UnaryExpr.h"
00008 #include "../Expression/replace.h"
00009 #include "../Info.h"
00010 #include "../macros.h"
00011 #include "../Wildcard/AnyOfType.h"
00012 #include "../Wildcard/WildcardOr.h"
00013
00014 #include "precalc_util.h"
00015 #include "lambda_util.h"
00016
00017 template class Info<int>;
00018 template class Info<LambdaInfo *>;
00019
00020
00021
00022 enum ARG_EVAL_TYPE {
00023 NON_STRICT,
00024 STRICT
00025 };
00026
00027 enum STRICT_BOOL {
00028 PRESERVE_TYPE = 0,
00029 MAKE_NON_STRICT = 1
00030 };
00031
00032 typedef RefDatabase<int, Expression>ArgDatabase;
00033
00034 template class Info<ArgDatabase *>;
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 class ArgExprElem : public Listable {
00046
00047 private:
00048 Expression * _e;
00049
00050 ARG_EVAL_TYPE _eval_type;
00051
00052 friend inline ostream & operator << (ostream & o, const ArgExprElem & h)
00053 { h.print(o); return o; }
00054
00055 public:
00056 ArgExprElem();
00057 ArgExprElem(Expression & e, ARG_EVAL_TYPE eval_type);
00058 ArgExprElem(const ArgExprElem & other);
00059
00060 ArgExprElem & operator = (const ArgExprElem & other);
00061
00062 virtual ~ArgExprElem();
00063
00064 Expression & expr() const;
00065
00066 ARG_EVAL_TYPE eval_type() const;
00067 void eval_type(ARG_EVAL_TYPE change_type);
00068
00069 virtual void print(ostream & o) const;
00070 virtual Listable *listable_clone() const;
00071 };
00072
00073 ArgExprElem::ArgExprElem()
00074 {
00075
00076 }
00077
00078 ArgExprElem::ArgExprElem(Expression & e,
00079 ARG_EVAL_TYPE eval_type)
00080 {
00081 _e = &e;
00082 _eval_type = eval_type;
00083 }
00084
00085 ArgExprElem::ArgExprElem(const ArgExprElem & other)
00086 {
00087 *this = other;
00088 }
00089
00090 ArgExprElem &
00091 ArgExprElem::operator = (const ArgExprElem & other)
00092 {
00093 _e = other._e;
00094 _eval_type = other._eval_type;
00095
00096 return *this;
00097 }
00098
00099 ArgExprElem::~ArgExprElem()
00100 {
00101
00102 }
00103
00104 Expression &
00105 ArgExprElem::expr() const
00106 {
00107 return *_e;
00108 }
00109
00110 ARG_EVAL_TYPE
00111 ArgExprElem::eval_type() const
00112 {
00113 return _eval_type;
00114 }
00115
00116 void
00117 ArgExprElem::eval_type(ARG_EVAL_TYPE change_type)
00118 {
00119 _eval_type = change_type;
00120 }
00121
00122 void
00123 ArgExprElem::print(ostream & o) const
00124 {
00125 _e->print(o);
00126
00127 o << ": ";
00128
00129 if (_eval_type == NON_STRICT)
00130 o << "Non-Strict";
00131 else
00132 o << "Strict";
00133 }
00134
00135 Listable *
00136 ArgExprElem::listable_clone() const
00137 {
00138 return new ArgExprElem(*this);
00139 }
00140
00141 template class TypedCollection<ArgExprElem>;
00142 template class List<ArgExprElem>;
00143 template ostream & operator << (ostream &, const List<ArgExprElem> &);
00144 template class Assign<ArgExprElem>;
00145
00146 template class Iterator<ArgExprElem>;
00147 template class Mutator<ArgExprElem>;
00148
00149
00150
00151
00152 class CollectPair {
00153 public:
00154 Expression &pattern;
00155 List<ArgExprElem> list;
00156
00157 CollectPair(Expression & replacement_pattern);
00158
00159 void absorb(CollectPair * absorbed,
00160 STRICT_BOOL lazy = PRESERVE_TYPE);
00161 };
00162
00163 CollectPair::CollectPair(Expression & replacement_pattern)
00164 :pattern(replacement_pattern)
00165 {
00166
00167 }
00168
00169
00170
00171
00172
00173 void
00174 CollectPair::absorb(CollectPair * absorbed,
00175 STRICT_BOOL lazy GIV(PRESERVE_TYPE))
00176 {
00177
00178
00179 for (Mutator<ArgExprElem> list_iter = absorbed->list;
00180 list_iter.valid(); ++list_iter) {
00181
00182 ArgExprElem *grabbed = list_iter.grab();
00183
00184
00185
00186
00187 if (lazy == MAKE_NON_STRICT)
00188 grabbed->eval_type(NON_STRICT);
00189
00190
00191 list.ins_last(grabbed);
00192 }
00193
00194
00195 delete absorbed;
00196 }
00197
00198 template class Info<CollectPair *>;
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229 void
00230 collect_lambda_formals(const Expression & e,
00231 ExtraInfo & extra_info)
00232 {
00233
00234 CollectPair & collect_pair = *((Info<CollectPair * >&) extra_info).data();
00235
00236 switch (e.op()) {
00237 case ARG_OP:
00238 {
00239
00240 ArgExprElem *arg_e
00241 = new ArgExprElem( CASTAWAY(Expression &) e, STRICT);
00242
00243
00244 collect_pair.list.ins_last(arg_e);
00245 break;
00246 }
00247
00248 case LAMBDA_CALL_OP:
00249 {
00250
00251 CollectPair *new_collect_pair
00252 = new CollectPair(collect_pair.pattern);
00253
00254
00255
00256
00257
00258 Info<CollectPair *> inf(new_collect_pair);
00259
00260 traverse(CASTAWAY(Expression &) e.arg_list()[1],
00261 new_collect_pair->pattern,
00262 collect_lambda_formals,
00263 inf, NON_RECURSIVE_REPLACE, PREORDER_REPLACE);
00264
00265
00266
00267 collect_pair.absorb(new_collect_pair);
00268 break;
00269 }
00270
00271 case MULT_OP:
00272 case OR_OP:
00273 case AND_OP:
00274 {
00275
00276 CollectPair *new_collect_pair
00277 = new CollectPair(collect_pair.pattern);
00278
00279
00280
00281 for (Iterator<Expression> expr_iter = e.arg_list();
00282 expr_iter.valid(); ++expr_iter) {
00283
00284 Info<CollectPair *> inf(new_collect_pair);
00285
00286 traverse(expr_iter.current(),
00287 new_collect_pair->pattern,
00288 collect_lambda_formals,
00289 inf, NON_RECURSIVE_REPLACE, PREORDER_REPLACE);
00290 }
00291
00292
00293
00294
00295 collect_pair.absorb(new_collect_pair, MAKE_NON_STRICT);
00296 }
00297 break;
00298 default: break;
00299 }
00300
00301 return;
00302 }
00303
00304
00305
00306
00307
00308
00309
00310 Expression *
00311 replace_lambda_call_expr(Expression * e, ExtraInfo & extra_info)
00312 {
00313 static AnyOfType *lambda_pattern = new AnyOfType(LAMBDA_CALL_OP);
00314 static AnyOfType *arg_pattern = new AnyOfType(ARG_OP);
00315 static WildcardOr *replace_pattern = new WildcardOr(lambda_pattern,
00316 arg_pattern);
00317
00318 Expression * return_expr;
00319
00320
00321
00322 switch(e->op()) {
00323 case LAMBDA_CALL_OP: {
00324 Assign<Expression> expr_as(e->arg_list().assign(1));
00325 expr_as = replace(e->arg_list().pull(1), *replace_pattern,
00326 replace_lambda_call_expr, extra_info,
00327 NON_RECURSIVE_REPLACE, PREORDER_REPLACE);
00328 return_expr = e;
00329 break;
00330 }
00331 default: {
00332
00333 ArgDatabase & argument_map = *((Info<ArgDatabase *>&) extra_info).data();
00334 Expression *reference_ptr = argument_map.find_ref(e->value());
00335 p_assert(reference_ptr, "Missing argument in replace_lambda_call_expr");
00336
00337 delete e;
00338
00339 return_expr = reference_ptr->clone();
00340 }
00341 }
00342 return return_expr;
00343 }
00344
00345
00346
00347
00348 Expression *
00349 replace_lambda_call(Expression * e,
00350 ExtraInfo & extra_info)
00351 {
00352
00353
00354 static AnyOfType *lambda_pattern = new AnyOfType(LAMBDA_CALL_OP);
00355 static AnyOfType *arg_pattern = new AnyOfType(ARG_OP);
00356 static AnyOfType *mult_pattern = new AnyOfType(MULT_OP);
00357 static AnyOfType *OR_pattern = new AnyOfType(OR_OP);
00358 static AnyOfType *AND_pattern = new AnyOfType(AND_OP);
00359 static WildcardOr *logical_pattern = new WildcardOr(OR_pattern, AND_pattern);
00360 static WildcardOr *non_strict_pattern = new WildcardOr(mult_pattern,
00361 logical_pattern);
00362 static WildcardOr *replace_pattern = new WildcardOr(lambda_pattern, arg_pattern);
00363 static WildcardOr *collect_pattern = new WildcardOr(replace_pattern, non_strict_pattern);
00364
00365
00366
00367 LambdaInfo & arg_map = *((Info<LambdaInfo * >&) extra_info).data();
00368
00369 ProgramUnit & pgm = *arg_map.program_ref;
00370 Statement & s = *arg_map.stmt_ref;
00371 LC_TYPE lc_type = arg_map.lc_type;
00372
00373 LambdaCallExpr & lambda_call_expr = *(LambdaCallExpr *) e;
00374
00375
00376
00377 if (lambda_call_expr.parameters_valid()) {
00378 Assign<Expression> lambda_as(lambda_call_expr.arg_list().assign(1));
00379 lambda_as = replace(lambda_call_expr.arg_list().pull(1),
00380 *lambda_pattern, replace_lambda_call, extra_info,
00381 RECURSIVE_REPLACE, PREORDER_REPLACE);
00382 }
00383
00384
00385 CollectPair collect_pair(*collect_pattern);
00386
00387
00388
00389
00390 Expression *repl_lambda_expr = lambda_call_expr.arg_list().pull(0);
00391
00392 Info<CollectPair *> inf(&collect_pair);
00393
00394 traverse(*repl_lambda_expr, collect_pair.pattern, collect_lambda_formals,
00395 inf, NON_RECURSIVE_REPLACE, PREORDER_REPLACE);
00396
00397
00398 ArgDatabase argument_map;
00399
00400
00401 List<Expression>ID_prototype_list;
00402
00403
00404 int arg_num = 1;
00405
00406 if (lambda_call_expr.parameters_valid())
00407
00408
00409
00410 for (Iterator<Expression> expr_iter
00411 = lambda_call_expr.parameters_guarded().arg_list();
00412 expr_iter.valid(); ++expr_iter) {
00413
00414
00415
00416 List<ArgExprElem> formal_list;
00417
00418 for (Mutator<ArgExprElem> elem_iter = collect_pair.list;
00419 elem_iter.valid(); ++elem_iter) {
00420 if (elem_iter.current_valid()) {
00421 if (elem_iter.current().expr().value() == arg_num)
00422 formal_list.ins_last(elem_iter.pull());
00423 }
00424 }
00425
00426
00427 Expression *actual_parm = &expr_iter.current();
00428
00429 while (actual_parm->op() == PAREN_OP)
00430 actual_parm = &actual_parm->expr_guarded();
00431
00432
00433
00434 switch (actual_parm->op()) {
00435 case INTEGER_CONSTANT_OP:
00436 case REAL_CONSTANT_OP:
00437 case COMPLEX_OP:
00438 case ID_OP:
00439 {
00440
00441
00442
00443 argument_map.ins(arg_num, *actual_parm);
00444 break;
00445 }
00446
00447 default:
00448 {
00449
00450
00451
00452
00453
00454 if ((formal_list.entries()>1) ||
00455 ((formal_list.entries() == 1) &&
00456 ((formal_list[0].eval_type() == NON_STRICT) &&
00457 (!actual_parm->is_side_effect_free())))) {
00458
00459
00460
00461
00462 Expression *ID_prototype
00463 = get_precalc(actual_parm->clone(), pgm, s);
00464
00465
00466
00467 ID_prototype_list.ins_last(ID_prototype);
00468
00469
00470
00471
00472 argument_map.ins(arg_num, *ID_prototype);
00473 }
00474 else {
00475
00476
00477 argument_map.ins(arg_num, *actual_parm);
00478 }
00479 }
00480 }
00481
00482 ++arg_num;
00483 }
00484
00485
00486
00487
00488
00489 {
00490 Info<ArgDatabase *> inf(&argument_map);
00491
00492 repl_lambda_expr =
00493 replace(repl_lambda_expr, *replace_pattern,
00494 replace_lambda_call_expr,
00495 inf, NON_RECURSIVE_REPLACE, PREORDER_REPLACE);
00496 }
00497
00498
00499
00500
00501
00502
00503
00504 if (lc_type == STMT_FUNCTION_CALL) {
00505 repl_lambda_expr = simplify(repl_lambda_expr);
00506 repl_lambda_expr = new UnaryExpr(PAREN_OP, repl_lambda_expr->type(),
00507 repl_lambda_expr);
00508 }
00509
00510 return repl_lambda_expr;
00511 }
00512
00513
00514
00515
00516
00517
00518
00519 Expression *
00520 remove_lambda_calls(Expression * e, LambdaInfo & lambda)
00521 {
00522
00523
00524 static AnyOfType lambda_pattern(LAMBDA_CALL_OP);
00525
00526
00527
00528 Info<LambdaInfo *> inf(&lambda);
00529
00530 return replace(e, lambda_pattern, replace_lambda_call,
00531 inf, RECURSIVE_REPLACE, PREORDER_REPLACE);
00532 }
00533
00534
00535
00536
00537
00538
00539
00540
00541 void
00542 remove_all_statement_functions(ProgramUnit & pgm)
00543 {
00544
00545
00546 LambdaInfo lambda(NULL, NULL, STMT_FUNCTION_CALL);
00547
00548 lambda.program_ref = &pgm;
00549
00550
00551
00552 for (Iterator<Statement> stmt_iter = pgm.stmts().iterator();
00553 stmt_iter.valid(); ++stmt_iter) {
00554 Statement *stmt_ref = &stmt_iter.current();
00555
00556 lambda.stmt_ref = stmt_ref;
00557
00558
00559
00560 for (Mutator<Expression> expr_mutr = stmt_ref->iterate_expressions();
00561 expr_mutr.valid(); ++expr_mutr) {
00562 if (expr_mutr.current_valid()) {
00563 Assign<Expression> expr_as(expr_mutr.assign());
00564 expr_as = remove_lambda_calls(expr_mutr.pull(), lambda);
00565 }
00566 }
00567
00568
00569 stmt_ref->build_refs();
00570 }
00571 }