array comprehension invoke( $() let temp : Array subexpr->type> for ..... if where .... push(temp, subexpr) return temp
| 117 | // push(temp, subexpr) |
| 118 | // return temp |
| 119 | ExpressionPtr generateComprehension ( ExprArrayComprehension * expr, bool tableSyntax ) { |
| 120 | auto compName = "__acomp_" + to_string(expr->at.line) + "_" + to_string(expr->at.column); |
| 121 | auto pClosure = new ExprBlock(); |
| 122 | pClosure->at = expr->subexpr->at; |
| 123 | pClosure->returnType = new TypeDecl(Type::autoinfer); |
| 124 | pClosure->generated = true; |
| 125 | // temp : Array<expr->subexpr->type> |
| 126 | auto pVar = new Variable(); |
| 127 | pVar->generated = true; |
| 128 | pVar->can_shadow = true; |
| 129 | pVar->at = expr->at; |
| 130 | pVar->name = compName; |
| 131 | pVar->type = new TypeDecl(Type::tArray); |
| 132 | pVar->type->constant = false; |
| 133 | pVar->type->removeConstant = true; |
| 134 | pVar->type->firstType = new TypeDecl(*expr->subexpr->type); |
| 135 | pVar->type->firstType->ref = false; |
| 136 | pVar->type->firstType->constant = false; |
| 137 | if ( expr->subexpr->type->isPointer() && expr->subexpr->type->constant ) { |
| 138 | if ( pVar->type->firstType->firstType ) { |
| 139 | pVar->type->firstType->firstType->constant = true; |
| 140 | } |
| 141 | } |
| 142 | // let temp |
| 143 | auto pLet = new ExprLet(); |
| 144 | pLet->at = expr->at; |
| 145 | pLet->atInit = expr->at; |
| 146 | pLet->visibility = static_cast<ExprFor*>(expr->exprFor)->visibility; |
| 147 | pLet->variables.push_back(pVar); |
| 148 | pClosure->list.push_back(pLet); |
| 149 | // push(temp, subexpr) |
| 150 | auto pPushVal = new ExprVar(); |
| 151 | pPushVal->at = expr->at; |
| 152 | pPushVal->name = compName; |
| 153 | auto pPush = new ExprCall(); |
| 154 | pPush->generated = true; |
| 155 | pPush->at = expr->at; |
| 156 | pPush->name = expr->subexpr->type->canCopy() ? "push" : "emplace"; |
| 157 | pPush->arguments.push_back(pPushVal); |
| 158 | pPush->arguments.push_back(expr->subexpr->clone()); |
| 159 | // for ... |
| 160 | auto pForBlock = new ExprBlock(); |
| 161 | pForBlock->at = expr->at; |
| 162 | pForBlock->inTheLoop = true; |
| 163 | if ( expr->exprWhere ) { |
| 164 | // push block |
| 165 | auto pPushBlock = new ExprBlock(); |
| 166 | pPushBlock->at = expr->at; |
| 167 | pPushBlock->list.push_back(pPush); |
| 168 | // for .... if where ... push |
| 169 | auto pIf = new ExprIfThenElse(); |
| 170 | pIf->at = expr->at; |
| 171 | pIf->cond = expr->exprWhere->clone(); |
| 172 | pIf->if_true = pPushBlock; |
| 173 | pForBlock->list.push_back(pIf); |
| 174 | } else { |
| 175 | // for .... push |
| 176 | pForBlock->list.push_back(pPush); |