| 1117 | } |
| 1118 | |
| 1119 | ExpressionPtr generateYield( ExprYield * expr, const FunctionPtr & func ) { |
| 1120 | const auto & yarg = func->arguments[1]; |
| 1121 | // TODO: verify yield type so that error is 'yield' error, not copy or move error |
| 1122 | auto LabelX = func->totalGenLabel ++; |
| 1123 | auto blk = new ExprBlock(); |
| 1124 | blk->isCollapseable = true; |
| 1125 | blk->at = expr->at; |
| 1126 | bool makeRef = false; |
| 1127 | if ( func->arguments.size()==2 ) { // starts with _ryield |
| 1128 | const auto & argn = func->arguments[1]->name; |
| 1129 | if ( argn.length()>=7 ) { |
| 1130 | makeRef = memcmp ( argn.c_str(), "_ryield", 7 ) == 0; |
| 1131 | } |
| 1132 | } |
| 1133 | if ( expr->moveSemantics ) { |
| 1134 | // TODO: error on makeRef + moveSemantics |
| 1135 | // result <- a |
| 1136 | auto mto = new ExprVar(expr->at, yarg->name); |
| 1137 | auto mfr = expr->subexpr->clone(); |
| 1138 | auto mve = new ExprMove(expr->at, mto, mfr); |
| 1139 | blk->list.push_back(mve); |
| 1140 | } else { |
| 1141 | // result = a |
| 1142 | auto cto = new ExprVar(expr->at, yarg->name); |
| 1143 | auto cfr = expr->subexpr->clone(); |
| 1144 | if ( makeRef ) { |
| 1145 | cfr = new ExprRef2Ptr(expr->at, cfr); |
| 1146 | cfr->alwaysSafe = true; |
| 1147 | } |
| 1148 | auto cpy = new ExprCopy(expr->at, cto, cfr); |
| 1149 | cpy->allowCopyTemp = true; // this is for generators which return temp# values |
| 1150 | blk->list.push_back(cpy); |
| 1151 | } |
| 1152 | // yield = X |
| 1153 | auto yyx = new ExprVar(expr->at, "__yield"); |
| 1154 | auto clx = new ExprConstInt(expr->at, LabelX); |
| 1155 | auto cpy = new ExprCopy(expr->at, yyx, clx); |
| 1156 | blk->list.push_back(cpy); |
| 1157 | // return true |
| 1158 | auto btr = new ExprConstBool(expr->at, true); |
| 1159 | auto rex = new ExprReturn(expr->at, btr); |
| 1160 | rex->fromYield = true; |
| 1161 | blk->list.push_back(rex); |
| 1162 | auto lbx = new ExprLabel(expr->at, LabelX, |
| 1163 | "yield at line " + to_string(expr->at.line)); |
| 1164 | blk->list.push_back(lbx); |
| 1165 | verifyGenerated(blk); |
| 1166 | return blk; |
| 1167 | } |
| 1168 | |
| 1169 | ExpressionPtr replaceGeneratorLet ( ExprLet * expr, const FunctionPtr & func, ExprBlock * scope ) { |
| 1170 | auto blk = new ExprBlock(); |