array comprehension generator( $() for ..... if where .... yield subexpr return false
| 210 | // yield subexpr |
| 211 | // return false |
| 212 | ExpressionPtr generateComprehensionIterator ( ExprArrayComprehension * expr ) { |
| 213 | auto pClosure = new ExprBlock(); |
| 214 | pClosure->at = expr->subexpr->at; |
| 215 | pClosure->returnType = new TypeDecl(Type::autoinfer); |
| 216 | // yield subexpr |
| 217 | auto pYield = new ExprYield(expr->at, expr->subexpr->clone()); |
| 218 | if ( !expr->subexpr->type->canCopy() ) { |
| 219 | pYield->moveSemantics = true; |
| 220 | } |
| 221 | // for ... |
| 222 | auto pForBlock = new ExprBlock(); |
| 223 | pForBlock->at = expr->at; |
| 224 | pForBlock->inTheLoop = true; |
| 225 | if ( expr->exprWhere ) { |
| 226 | // yield block |
| 227 | auto pPushBlock = new ExprBlock(); |
| 228 | pPushBlock->at = expr->at; |
| 229 | pPushBlock->list.push_back(pYield); |
| 230 | // for .... if where ... yield |
| 231 | auto pIf = new ExprIfThenElse(); |
| 232 | pIf->at = expr->at; |
| 233 | pIf->cond = expr->exprWhere->clone(); |
| 234 | pIf->if_true = pPushBlock; |
| 235 | pForBlock->list.push_back(pIf); |
| 236 | } else { |
| 237 | // for .... yield |
| 238 | pForBlock->list.push_back(pYield); |
| 239 | } |
| 240 | auto pFor = static_cast<ExprFor*>(expr->exprFor->clone()); |
| 241 | pFor->body = pForBlock; |
| 242 | pClosure->list.push_back(pFor); |
| 243 | // return false |
| 244 | auto pRet = new ExprReturn(); |
| 245 | pRet->at = expr->at; |
| 246 | pRet->subexpr = new ExprConstBool(expr->at, false); |
| 247 | pClosure->list.push_back(pRet); |
| 248 | // make block |
| 249 | auto pMakeBlock = new ExprMakeBlock(expr->at,pClosure); |
| 250 | // generator |
| 251 | auto pMkGen = new ExprMakeGenerator(expr->at, pMakeBlock); |
| 252 | pMkGen->iterType = new TypeDecl(*expr->subexpr->type); |
| 253 | pMkGen->alwaysSafe = expr->alwaysSafe; |
| 254 | return pMkGen; |
| 255 | } |
| 256 | |
| 257 | /* a->b(args) is short for invoke(a.b, cast<auto> deref(a), args) */ |
| 258 | ExprInvoke * makeInvokeMethod ( const LineInfo & at, Expression * a, const string & b ) { |