[Bro-Dev] [Proposal] Language extensions for better Broker support

Matthias Vallentin vallentin at icir.org
Sun Dec 11 03:49:06 PST 2016


> Personally, I see this more as a question of readability (as opposed
> to typeability :). But it's a matter of taste, and I'd be fine with
> using "as" instead of "cast<>".

Probably aligned with that thought is consistency and intuition: we
don't have C++-style angle brackets in Bro, so "as" feels more in line
with, e.g., type declarations of the form table[T] of U. Angle brackets
would feel like a one-off, whereas space-separated short keywords fit in
more naturally.

> I'm thinking such errors need to be addressed by the function itself,
> using whatever mechanism it deems appropriate (e.g., signaling trouble
> through its return value). The problem is that we don't have any
> further error handling mechanisms (e.g., exceptions) in the language
> right now (that's a project for some other time). I see timeouts as
> different as that's something the function itself may have a hard time
> catching internally, if at all; we couldn't rely on that. It's kind of
> last line of defense against trouble: if for whatever reason the
> function ends up never returning, we'll catch it and clean up at
> least.

Indeed, timeouts are a last line of defense and generated by the
runtime, as opposed to the function itself. You point out that these are
two separate kinds of errors.

However, from a user perspective, I think errors should be treated
uniformly. For example, when performing a Broker store lookup of a key,
but the returned value has a type different than expected, script
execution (in particular: a chain of asynchronous functions) should not
continue. The same thing happens for a timeout, even though the
runtime---as opposed to the actual function---generated the error. 

The alternative strikes me as complicated, because it is application
dependent. If a response to an asynchronous request doesn't arrive
within a time bound, *the effect* might be equivalent to an error within
the function itself. An invalid cast might generated a runtime error to
the console (as Bro does now for use of uninitialized variables) and
abort, whereas a timeout would simply abort.

In Bro, one way to represent represent errors would be as a record with
an optional error field. If the field is set, an error took place and
one can examine it. Either the function returns one of these explicitly,
or the runtime (i.e., the interpreter) populates one.

Here's a strawman of what I mean:

    type result = record {
      error: failure &optional;
      value: any &optional;
    }

    function f(x: T) : result {
      if (store lookup with bad cast)
        return [$error=..];
      if (nothing to do)
        return [];
      if (computed something)
        return [$data=42];
    }

    local r = f(x);
    if (r$?error) {
      // handle error, check if timeout or some other form of error
      // occurred by inspecting the failure instance.
    }

Then, the runtime would allow for automatic chaining of asynchronous
functions returning instances of type result:

    function f(x: T) : result;
    function g(y: U) : result;

    // Calls g iff f did not fail and return value unpacking succeeded.
    local r = g(f(x));

Here, the runtime could do the unpacking of f's result, checking for
errors, and feeding the result data into g---assuming types work out.

In essence, this is a monad for a fixed set of types. The runtime
performs the unboxing of return values automatically. 

    Matthias


More information about the bro-dev mailing list