packages/deriver/src/Deriver/Evaluator/Call/Plan/Expression.php

1<?php
2
3declare(strict_types=1);
4
5namespace Deriver\Deriver\Evaluator\Call\Plan;
6
7use Deriver\Deriver\Evaluator\Call\Plan\Location\LocationRef;
8use Deriver\Deriver\Evaluator\Term;
9
10/**
11 * A pure plan expression referencing parameters, state, or registered operations.
12 *
13 * @visibility root
14 * @example Keeping a symbolic parameter
15 *     \Deriver\Deriver\Evaluator\Call\Plan\Expression::parameter('id')->name // => 'id'
16 */
17final class Expression
18{
19    /**
20     * @param ExpressionKind $operation Plan expression operation
21     * @param string $name Parameter, intrinsic, slot, or operator name
22     * @param list<self> $operands Ordered subexpressions
23     * @param Term|null $constant Literal value
24     * @param LocationRef|null $location Storage read by a location expression
25     */
26    public function __construct(public readonly ExpressionKind $operation, public readonly string $name = '', public readonly array $operands = [], public readonly ?Term $constant = null, public readonly ?LocationRef $location = null)
27    {
28    }
29
30    /**
31     * Refers to a normalized parameter or a prior action's result.
32     * @param string $name Bound parameter name
33     * @return self Parameter expression
34     */
35    public static function parameter(string $name): self
36    {
37        return new self(ExpressionKind::Parameter, $name);
38    }
39
40    /**
41     * Embeds an immutable term.
42     * @param Term $value Literal or structured input
43     * @return self Constant expression
44     */
45    public static function literal(Term $value): self
46    {
47        return new self(ExpressionKind::Constant, constant: $value);
48    }
49
50    /**
51     * Refers to the bound receiver.
52     * @return self Receiver expression
53     */
54    public static function receiver(): self
55    {
56        return new self(ExpressionKind::Parameter, 'this');
57    }
58
59    /**
60     * Uses the same PHP binary semantics as a source expression.
61     * @param string $operator PHP operator
62     * @param self $left Left operand
63     * @param self $right Right operand
64     * @return self Binary expression
65     */
66    public static function binary(string $operator, self $left, self $right): self
67    {
68        return new self(ExpressionKind::Binary, $operator, [$left, $right]);
69    }
70
71    /**
72     * Reads a namespaced abstract object slot.
73     * @param string $slot Domain-qualified slot name
74     * @param self|null $receiver Object expression; omitted means this
75     * @return self State expression
76     */
77    public static function state(string $slot, ?self $receiver = null): self
78    {
79        return new self(ExpressionKind::State, $slot, [$receiver ?? self::receiver()]);
80    }
81
82    /**
83     * Reads a parameter, state slot, or array element through core storage semantics.
84     * @param LocationRef $location Declarative address
85     * @return self Storage read expression
86     */
87    public static function read(LocationRef $location): self
88    {
89        return new self(ExpressionKind::LocationRead, location: $location);
90    }
91}
92