• Nils Goroll's avatar
    Enable calling a dynamic sub · 7ec28f1a
    Nils Goroll authored
    that is,
    
    	call vmod.returning_sub();
    
    in VCL.
    
    Background:
    
    The existing
    
    	call sub;
    
    is special in that it instantiates "sub", if it does not exist
    already, enabling use-before-definition semantics.
    
    The doctrine of this change is to preserve this behaviour and to not
    make existing, static calls any less efficient.
    
    Implementation:
    
    To support calling both literal SUBs as well as SUB expressions, we
    peek into the symbol table to check if the called expression is a
    function, based on the knowledge that, as of now, only functions can
    have a non-literal SUB return. We also know that no other expression
    can yield a SUB. So if peeking ahead tells us that a function follows,
    we call into expression evaluation.
    
    Otherwise, we expect a literal SUB as before.
    
    Null check:
    
    For dynamic SUB calls from vmods via VRT_call(), we require the SUB
    argument be non-NULL. But we can not for call: To signal error with a
    SUB return, a vmod function needs to be allowed to return NULL,
    otherwise it would need to have a dummy return value available for the
    VRT_fail() case. So we need to check for NULL in VGC.
    
    Alternatives considered:
    
    - We could make expression evaluation return SUB also for literal SUB
    symbols, turning all calls into sub->func(ctx, ...) C statements. I
    tried this path and it resulted in a change of behaviour with
    cc_command="clang -g -O2 ...": Where, previously, sub code was
    inlined, it would now generate an explicit C function call always,
    despite the fact that the C function is known at compile time (because
    all named VCL_SUB structs are).
    
    So this option was dismissed for violating the doctrine.
    
    - The null check could go to VPI, via a VPI_call(), basically identical
    to VRT_call(), but checking for NULL. This option was dismissed because
    it would foreclose the requirement to allow for SUB arguments in the
    future.
    
    Acknowledgements:
    
    reza mentioned the idea of call SUB at one point, and I can not remember
    if I had it before or not, so when in doubt, it was his idea.
    
    Dridi helped with ideas on the implementation and spotted a bug.
    7ec28f1a