| 1167 | } |
| 1168 | |
| 1169 | ExpressionPtr replaceGeneratorLet ( ExprLet * expr, const FunctionPtr & func, ExprBlock * scope ) { |
| 1170 | auto blk = new ExprBlock(); |
| 1171 | blk->at = expr->at; |
| 1172 | blk->isCollapseable = true; |
| 1173 | auto capture = func->arguments[0]->type->structType; |
| 1174 | DAS_ASSERT(capture && "generator first argument is lambda capture"); |
| 1175 | for ( auto & var : expr->variables ) { |
| 1176 | auto vtd = new TypeDecl(*var->type); |
| 1177 | bool isRef = vtd->ref; |
| 1178 | if ( isRef ) { |
| 1179 | auto pvtd = new TypeDecl(Type::tPointer); |
| 1180 | pvtd->firstType = vtd; |
| 1181 | vtd->ref = false; |
| 1182 | vtd = pvtd; |
| 1183 | replaceRef2Ptr(scope, var->name); |
| 1184 | } else { |
| 1185 | vtd->constant = false; |
| 1186 | } |
| 1187 | // the reason we insert after __lambda and __finalize is so that when we have iterators, we delete them before we delete captured variables |
| 1188 | capture->fields.emplace_back( |
| 1189 | var->name, |
| 1190 | vtd, |
| 1191 | nullptr, |
| 1192 | AnnotationArgumentList(), |
| 1193 | false, |
| 1194 | expr->at); |
| 1195 | auto & fldb = capture->fields.back(); |
| 1196 | if ( isRef || var->do_not_delete ) { |
| 1197 | fldb.doNotDelete = true; |
| 1198 | } |
| 1199 | fldb.capturedConstant = var->type->constant; |
| 1200 | auto cvar = new ExprVar(var->at, func->arguments[0]->name); |
| 1201 | auto lvar = new ExprField(var->at, cvar, var->name); |
| 1202 | lvar->ignoreCaptureConst = true; |
| 1203 | if ( var->init ) { |
| 1204 | auto rini = var->init->clone(); |
| 1205 | if ( isRef ) { |
| 1206 | auto arini = new ExprRef2Ptr(expr->at, rini); |
| 1207 | arini->alwaysSafe = true; |
| 1208 | rini = arini; |
| 1209 | } |
| 1210 | if ( var->init_via_clone ) { |
| 1211 | auto cln = new ExprClone(var->at, lvar, rini); |
| 1212 | blk->list.push_back(cln); |
| 1213 | } else if ( var->init_via_move ) { |
| 1214 | auto mve = new ExprMove(var->at, lvar, rini); |
| 1215 | blk->list.push_back(mve); |
| 1216 | } else { |
| 1217 | auto cpy = new ExprCopy(var->at, lvar, rini); |
| 1218 | blk->list.push_back(cpy); |
| 1219 | } |
| 1220 | } else { |
| 1221 | auto mz = new ExprMemZero(var->at, "memzero"); |
| 1222 | mz->arguments.push_back(lvar); |
| 1223 | blk->list.push_back(mz); |
| 1224 | } |
| 1225 | } |
| 1226 | verifyGenerated(blk); |
no test coverage detected