Let me start by saying that I have an actual use case for this in the measurement framework and I'm not just messing around.
function add_x(x: count): function(a: count): count
{
local tmp = function(a: count): count
{
# The 'x' variable ends up receiving the value of the same arity as my inner
# defined function instead of the value of the outer scope where 'x' is.
return a+x;
};
return tmp;
}
event bro_init()
{
local my_adder = add_x(5);
print my_adder(1); # hopefully would print 6, but it prints 2
local your_adder = add_x(100);
print your_adder(2); # hopefully would print 102, but it prints 4
}
Would this functionality working like I wish it did be difficult? It would make a very nice usability feature for the measurement framework when setting thresholds.
Would this functionality working like I wish it did be difficult?
First, as best as I can figure, the current functionality is seriously
broken. It's reaching into a interpreter stack frame at the offset
associated with x. That just happens to be the offset associated with 'a'
during your my_addr()/your_addr() invocations, which is why the output is
a doubling of 'a'.
Indeed, I've confirmed that if your outer function had an additional
argument that comes before 'x', then the my_addr()/your_addr() invocations
crash.
To fix this, it makes sense that for functions defined inside other
functions, there's a clear binding model. The only trick is what
that model should be. If it's bind-on-function-creation, then you'd
get the semantics you desire. But I suspect there are other uses
for such interior funtions where bind-on-application is handy - *providing*
of course that the interior function doesn't escape to the exterior like
it does in your example.
My proposal would be to introduce bind-on-function-creation semantics,
and if later we find we sometimes want bind-on-application semantics,
introduce that using an attribute.
But there's still the "would this .... be difficult" question. I suspect
it's going to be messy. I'm having a hard time seeing how it doesn't
involve a full parse-tree traversal of the interior function's body during
creation. (And I leave the problem of the interior function itself having
an interior function as an exercise for the reader.