| 683 | } |
| 684 | |
| 685 | FunctionPtr generateLambdaFunction ( const string & lambdaName, ExprBlock * block, |
| 686 | const StructurePtr & ls, const safe_var_set & capt, |
| 687 | const vector<CaptureEntry> & capture, uint32_t genFlags, Program * thisProgram ) { |
| 688 | auto lfn = lambdaName + "`function"; |
| 689 | auto pFunc = new Function(); |
| 690 | pFunc->lambda = true; |
| 691 | pFunc->generated = true; |
| 692 | pFunc->at = pFunc->atDecl = block->at; |
| 693 | pFunc->name = lfn; |
| 694 | pFunc->privateFunction = true; |
| 695 | pFunc->requestJit = (genFlags & generator_jit)!=0; |
| 696 | pFunc->requestNoJit = (genFlags & generator_nojit)!=0; |
| 697 | auto fb = new ExprBlock(); |
| 698 | fb->at = block->at; |
| 699 | auto with = new ExprWith(block->at); |
| 700 | with->with = new ExprVar(block->at, "__this"); |
| 701 | with->with->generated = true; |
| 702 | with->body = block->clone(); |
| 703 | ((ExprBlock *) with->body)->isLambdaBlock = false; // this is now a body of the function, not a lambda block |
| 704 | static_cast<ExprBlock*>(with->body)->finalList.clear(); |
| 705 | if ( genFlags & generator_needYield ) { |
| 706 | pFunc->generator = true; |
| 707 | auto bbl = static_cast<ExprBlock*>(with->body); |
| 708 | // goto __yeild |
| 709 | auto gvar = new ExprVar(block->at, "__yield"); |
| 710 | auto gexpr = new ExprGoto(block->at, static_cast<Expression*>(gvar)); |
| 711 | bbl->list.insert(bbl->list.begin(), gexpr); |
| 712 | // label "0" |
| 713 | auto lzero = new ExprLabel(block->at, pFunc->totalGenLabel); |
| 714 | bbl->list.insert(bbl->list.begin() + 1, lzero); |
| 715 | pFunc->totalGenLabel ++; |
| 716 | } |
| 717 | auto wb = static_cast<ExprBlock*>(with->body); |
| 718 | wb->blockFlags = 0; |
| 719 | wb->arguments.clear(); |
| 720 | wb->returnType = nullptr; |
| 721 | fb->list.push_back(with); |
| 722 | pFunc->body = fb; |
| 723 | pFunc->result = new TypeDecl(*block->type); |
| 724 | auto cTHIS = new Variable(); |
| 725 | cTHIS->generated = true; |
| 726 | cTHIS->at = block->at; |
| 727 | cTHIS->name = "__this"; |
| 728 | cTHIS->type = new TypeDecl(ls); |
| 729 | cTHIS->type->isExplicit = true; |
| 730 | pFunc->arguments.push_back(cTHIS); |
| 731 | for ( auto & arg : block->arguments ) { |
| 732 | auto cA = arg->clone(); |
| 733 | cA->marked_used = true; // to avoid 'unused argument' error |
| 734 | pFunc->arguments.push_back(cA); |
| 735 | } |
| 736 | for ( auto & var : capt ) { |
| 737 | CaptureMode mode = CaptureMode::capture_any; |
| 738 | auto it = find_if ( capture.begin(), capture.end(), [&] ( const auto & entry ){ |
| 739 | return entry.name == var->name; |
| 740 | }); |
| 741 | if ( it != capture.end() ) { |
| 742 | mode = it->mode; |
no test coverage detected