Operators

Each operator is given with its signature, consisting of a list of allowed typings, tried in order.
A typing is of the form type1, …, typenreturn-type.

Arithmetic

  • addition, concatenation:
    • + : int, int → int
    • + : uint, uint → uint
    • + : float, float → float
    • + : ctime, ctime → ctime
    • + : ctime, int → ctime
    • + : ctime, timeval → timeval
    • + : timeval, int → timeval
    • + : timeval, ctime → timeval
    • + : timeval, timeval → timeval
      Note: all of the above forms implement truncated addition, not addition modulo 2N for any N. This is done so that addition is monotonic in its arguments.
    • + : str, str → str (string concatenation)
    • + : db[type1, …, typen], db[type1, …, typen] → db[type1, …, typen]
    • + : db[*], db[type1, …, typen] → db[type1, …, typen]
    • + : db[type1, …, typen], db[*] → db[type1, …, typen]
    • + : db[*], db[*] → db[*]
      (database union)
      Note: the two input database types must be identical, or at least one of them is the special type db[*] that only the empty database can have..
  • subtraction:
    • - : int, int → int
    • - : uint, uint → uint
    • - : float, float → float
    • - : ctime, ctime → ctime
    • - : ctime, int → ctime
    • - : timeval, int → timeval
    • - : timeval, ctime → timeval
    • - : timeval, timeval → timeval
      Note: all of the above forms implement truncated subtraction, not subtraction modulo 2N for any N. This is done so that subtraction is monotonic in its first argument, and antitonic in its second argument.
    • - : db[type1, …, typen], db[type1, …, typen] → db[type1, …, typen]
    • - : db[*], db[type1, …, typen] → db[*]
    • - : db[type1, …, typen], db[*] → db[type1, …, typen]
    • - : db[*], db[*] → db[*]
      (database difference)
      Note: the two input database types must be identical, or at least one of them is the special type db[*] that only the empty database can have.
      Computes first database without all the tuples of the second database.
  • opposite:
    • - : int → int
      Note: the above form implements truncated opposite, not opposite modulo 2N for any N. This is done so that opposite is monotonic in its argument. The only surprising case is taking the opposite of the least possible int (-2N-1, where N is the bit size), which yields the largest possible int (2N-1-1) instead of the modulo value, -2N.
    • - : uint → int
      Again, this is truncated opposite.
    • - : float → float
  • same sign conversion:
    • + : int → int
      The identity map.
    • + : uint → int
      Conversion from unsigned to signed integer. This is truncated conversion, not conversion module 2N for any N. This is done so as to be monotonic in its argument. Any number strictly greater than -LONG_MIN is converted to LONG_MIN
    • + : float → float
      The identity map.
  • multiplication:
    • * : int, int → int
    • * : uint, uint → uint
      Note: the above forms implement multiplication modulo word size, and are not monotonic.
    • * : float, float → float
  • division:
    • / : int, int → int (quotient)
    • / : uint, uint → uint (quotient)
      Note: the above forms implement multiplication modulo word size, and are not monotonic.
    • / : float, float → float (division)
  • modulo:
    • % : int, int → int
    • % : uint, uint → uint

Bitwise logic

  • bitwise and:
    • & : type1, type2 type1
      where type1, type2 are any types among int, uint, ipv4.
    • & : ipv6, ipv6 → ipv6
  • bitwise or:
    • | : type1, type2 type1
      where type1, type2 are any types among int, uint, ipv4.
    • | : ipv6, ipv6 → ipv6
  • bitwise exclusive or:
    • ^ : type1, type2 type1
      where type1, type2 are any types among int, uint, ipv4.
    • ^ : ipv6, ipv6 → ipv6
  • bitwise not:
    • ~ : int → int
    • ~ : int → int
    • ~ : ipv4 → ipv4
    • ~ : ipv6 → ipv6

Logic

As in C, int is equated with the type of booleans, 0 is false, everything else is true.

  • logical and:
    • && : int, int → int
  • logical or:
    • || : int, int → int
  • logical negation:
    • ! : int → int
  • equality:
    • == : type, type → int
    • != : type, type → int

    where type is any type among int, uint, float, str, ctime, timeval, ipv4, ipv6, or a database type db[type1, …, typen];
    note that the two arguments must be of the same type—an exception is given by the following typing rules, which apply to the very special case of comparisons with the empty database

    • ==!= : db[*], db[type1, …, typen] → int
    • ==, != : db[type1, …, typen], db[*] → int
    • ==, != : db[*], db[*] → int
  • order:
    • <= : type, type → int
    • < : type, type → int
    • >= : type, type → int
    • > : type, type → int

    where type is any type among int, uint, float, str, ctime, timeval, ipv4, ipv6, or a database type db[*] or db[type1, …, typen] (databases are compared for inclusion); the ordering is:

    • the natural ordering on data of types int, uint, float, ctime, timeval,
    • the lexicographic ordering on strings (of type str), seen as byte strings—not any fancier ordering such as UTF8 collation order: that may come, but no field of type str is currently flagged as monotonic anyway;
    • ipv4 addresses are compared as though they were unsigned 32-bit integers;
    • ipv6 addresses are compared lexicographically, considering they are 16-byte strings;
    • databases, of type db[*] or db[type1,, typen], are compared for inclusion.

    Note that the two arguments must be of the same type—an exception is given by the following typing rules, which apply to the very special case of comparisons with the empty database

    • <=, <, >=, > : db[*], db[type1, …, typen] → int
    • <=, <, >=, > : db[type1, …, typen], db[*] → int
    • <=, <, >=, > : db[*], db[*] → int
  • regexp matching:
    • =~ : str, regex → int
      return true if string matches regexp
    • !~ : str, regex → int
      return true if string does not match regexp