packages/deriver/src/Deriver/Evaluator/Invocation/Bodies.php
1<?php
2
3declare(strict_types=1);
4
5namespace Deriver\Deriver\Evaluator\Invocation;
6
7use Deriver\Deriver\Evaluator\CallEvaluation;
8use Deriver\Deriver\Evaluator\Evaluator;
9use Deriver\Deriver\Evaluator\Scope\Frame;
10use Deriver\Deriver\Lowerer\Graph\Instruction;
11
12/**
13 * The only candidate entry to source or evaluator implementations.
14 * @visibility parent
15 */
16final class Bodies
17{
18 /**
19 * Uses the current dependency context.
20 */
21 public function __construct(private readonly Evaluator $engine)
22 {
23 }
24
25 /**
26 * Selects once per call and bindings, before inspecting effects.
27 */
28 public function select(Frame $caller, Instruction $call, string $target, int $depth): Body
29 {
30 $context = $this->engine->context;
31 $key = $caller->identity . ':' . $call->id . ':' . $target;
32 if (isset($context->implementations[$key])) {
33 return $context->implementations[$key];
34 }
35 $request = new \Deriver\Deriver\Evaluator\Micro\Request($this->engine, $caller, $call, $depth, $target);
36 $builtin = new CallEvaluation($this->engine);
37 $evaluator = (new \Deriver\Deriver\Evaluator\Micro\Dispatch())->evaluate($request, $builtin);
38 return $context->implementations[$key] = new Body($evaluator ?? $context->index->graph($target), $evaluator !== null);
39 }
40}
41