The Variable System#

EQL variables are more than just placeholders; they are active components of the execution graph that know how to resolve data from object instances.

HasSymbolicOperations#

The HasSymbolicOperations mixin is what makes EQL so “pythonic.” It overrides standard Python dunder methods to capture operations and turn them into symbolic expressions.

  • __getattr__: Captures attribute access and returns an Attribute.

  • __getitem__: Captures indexing and returns an Index.

  • __call__: Captures method calls and returns a Call.

  • __eq__ and the other comparisons: Return a Comparator.

  • The arithmetic dunders: Return an ArithmeticOperation.

Hint

This is why you can write robot.name == "R2D2". The robot variable captures the .name access and returns a symbolic Attribute node.

Each operation is built on the expression the implementation reports as _symbolic_expression_, which is what lets something that is not itself part of the expression graph offer the same operations: a Match reports the query it lowers to, so a(Drawer).body is that query’s attribute.

CanBehaveLikeAVariable#

The CanBehaveLikeAVariable mixin is the other half: the expression those operations are built on. It reports itself as _symbolic_expression_, and holds the mappings taken from it, so writing the same one twice gives one node rather than two - which is why robot.name is robot.name.

Mapped Variables#

A MappedVariable is a UnaryExpression that transforms the value of its child.

1. Attribute#

Represents access to a Python attribute. During evaluation, it uses getattr(value, name).

2. Index#

Represents access to a dictionary key or list index. It uses value[key].

3. Call#

Represents a symbolic method call. It stores the arguments and keyword arguments, and executes the call during evaluation.

Note

Mapped variables are cached internally to ensure that the same symbolic path (e.g., robot.name) always resolves to the same expression object within a query context.

Flattening with FlatVariable#

The FlatVariable is a special mapped variable used when an attribute returns an iterable, but you want to treat its elements as individual bindings in the result stream.

Note

Use flat_variable() explicitly when you want to iterate over elements of attributes that are iterable. Standard attribute access on an iterable valued attribute will return the iterables as values, not their elements.

API Reference#