| 295 | } |
| 296 | |
| 297 | std::shared_ptr<Expr> compileLambda( |
| 298 | const core::LambdaTypedExpr* lambda, |
| 299 | Scope* scope, |
| 300 | const core::QueryConfig& config, |
| 301 | memory::MemoryPool* pool, |
| 302 | const std::unordered_set<std::string>& flatteningCandidates, |
| 303 | bool enableConstantFolding) { |
| 304 | auto signature = lambda->signature(); |
| 305 | auto parameterNames = signature->names(); |
| 306 | Scope lambdaScope(std::move(parameterNames), scope, scope->exprSet); |
| 307 | auto body = compileExpression( |
| 308 | lambda->body(), |
| 309 | &lambdaScope, |
| 310 | config, |
| 311 | pool, |
| 312 | flatteningCandidates, |
| 313 | enableConstantFolding); |
| 314 | |
| 315 | // The lambda depends on the captures. For a lambda caller to be |
| 316 | // able to peel off encodings, the captures too must be peelable. |
| 317 | std::vector<std::shared_ptr<FieldReference>> captureReferences; |
| 318 | captureReferences.reserve(lambdaScope.capture.size()); |
| 319 | for (auto i = 0; i < lambdaScope.capture.size(); ++i) { |
| 320 | auto expr = lambdaScope.captureFieldAccesses[i]; |
| 321 | auto reference = getAlreadyCompiled(expr, &scope->visited); |
| 322 | if (!reference) { |
| 323 | auto inner = lambdaScope.captureReferences[i]; |
| 324 | reference = std::make_shared<FieldReference>( |
| 325 | inner->type(), std::vector<ExprPtr>{}, inner->field()); |
| 326 | scope->visited[expr] = reference; |
| 327 | } |
| 328 | captureReferences.emplace_back( |
| 329 | std::static_pointer_cast<FieldReference>(reference)); |
| 330 | } |
| 331 | |
| 332 | auto functionType = std::make_shared<FunctionType>( |
| 333 | std::vector<TypePtr>(signature->children()), body->type()); |
| 334 | return std::make_shared<LambdaExpr>( |
| 335 | std::move(functionType), |
| 336 | std::move(signature), |
| 337 | std::move(captureReferences), |
| 338 | std::move(body), |
| 339 | config.exprTrackCpuUsage()); |
| 340 | } |
| 341 | |
| 342 | ExprPtr tryFoldIfConstant(const ExprPtr& expr, Scope* scope) { |
| 343 | if (expr->isConstant() && scope->exprSet->execCtx()) { |
no test coverage detected