165 Optimisation

Implementation Note: Entity Value Storage and Reference Resolution

Although Predica treats entities as pure values whose identity is defined solely by their keys, a real implementation will typically store these values in efficient data structures such as hash maps, B-trees, or red-black trees. These structures index entity values by their keys so that expressions like:


..supplier[id=1]

can be resolved efficiently.

When a system literal is evaluated, the implementation can be viewed as proceeding in two conceptual phases:

  1. Populate entity sets
    All top-level entity sets (for example, supplier*, part*) are constructed first and indexed by their keys.
  2. Resolve entity references
    Expressions such as ..supplier[id=1] are then evaluated by performing a lookup in the corresponding index. If the key is present, the implementation returns the actual entity value stored in the set. If the key is missing, for example:
    
    Shipment { supplier = ..supplier[id=9], part = ..part[id=5], qty = 400 }
        
    If that expression is evaluated, the implementation reports an error because no entity with that key exists in the system literal.

These internal indices necessarily assign implementation-level identifiers or handles to entity values. However, these identifiers are not part of Predica’s semantics:

  • they are not visible to the user;
  • they do not participate in equality;
  • they do not define identity;
  • they do not appear in literals or queries.

They exist solely to support efficient lookup and value sharing. Predica’s semantics remain purely value-based, with identity determined only by keys.

Optimisation using the statically declared cardinality constraints

The compiler optimiser can and will use the statically defined cardinality constraints. An important one is an exactly one constraint because the compiler doesn't need to use a set. This is important because many attributes are exactly one.

entity Supplier
{
    Integer id;
    String name;
    Integer status;
    String city;
    key {id};
}

Every attribute has exactly one value. This means the compiler knows, statically that id, name, status and city are scalars. There is no need to represent these as sets or collections internally. This is a huge optimisation lever.