- assignment: $var
=
expr
$var[expr1][expr2]…[exprn]=expr
evaluate expr and assign its value val to variable $var, or to the entry indexed expr1, expr2, …, exprn in array $var.
return value val
Typing:- Requires: $var and expr have the same type type
- Yields: result of type type
- variables $var
$
[A
–Za
–z_
][A
–Za
–z0
–9_.
]*
ordinary variables, can be read and assigned to
type will be inferred automatically
- array elements $var[expr1][expr2]…[exprn]
where $var holds an n-dimensional array
again, type and dimensionality will be inferred automatically
the indices expr1, expr2, …, exprn can have any basic type (int
,uint
,str
,bstr
,ipv4
,ipv6
, etc.), and one can even use indices of different types for the same array
- logical variables Var [
A
–Z
][A
–Za
–z0
–9_.
]*
start with a capital letter
used in database collections
can be read but not assigned to
type will be inferred automatically
- constants:
- integer constants [
0
–9
]+
type:uint
- integer constants do not start with a sign; if you write
-123
, this will be interpreted as the arithmetic operator-
applied to the number123
, resulting in an expression of typeint
, notuint
- integer constants do not start with a sign; if you write
- floating-point constants ([
0
–9
]*\.
[0
–9
]+)([eE
][-+
]?[0
–9
]+)?
type:float
- these are really double precision floating-point numbers, equivalent to
double
in C
- these are really double precision floating-point numbers, equivalent to
- string constants
See the STRING token on the Orchids language page
type:str
- as in C, writing two or more string constants in succession produces their concatenation; this allows one to write multi-line string constants, notably
- as in C, writing two or more string constants in succession produces their concatenation; this allows one to write multi-line string constants, notably
- ctime constants
_CTIME(
integer constant)
,
or_CTIME(
string constant)
type:ctime
the first syntax uses a number of seconds since the epoch (January 1, 1970)
- while the second syntax uses a human-readable date string
- ipv4 constants
_IPV4(
string constant)
type:ipv4
- string can be of the form “aa
.
bb.
cc.
dd“, or “host.subnet.domain“
- string can be of the form “aa
- ipv6 constants
_IPV6(
string constant)
type:ipv6
- string can be of the form “aa
:
bb:
cc:
dd:
ee:
ff:
gg” (or any of the usual variants), or “host.subnet.domain“
- string can be of the form “aa
- timeval constants
_TIMEVAL(
integer constant,
integer constant)
,
or_TIMEVAL(
string constant,
integer constant)
type:timeval
- the first syntax uses a pair of a number of seconds and a number of microseconds
- the second syntax instead specifies the number of seconds as a date, in a human-readable format
- regexp constants
_REGEX(
string constant)
type:regex
actually compiles the given string to a regexp-matching machine,
usable as second argument to operators=~
, !~
- integer constants [
- expr1
binop expr2
where binop is a binary operator
- monop expr
where monop is a unary operator
- function
(
expr1,
…,
exprn)
evaluate expr1,
…,
exprn, yielding values val1,
…,
valn, then call function on the latter- function must be one of the Orchids primitives, defined in the core language or in one of the modules
- synthetic event: .{field1
=
expr1,
…,
fieldn=
exprn}
create a synthetic event- evaluate expr1, …, exprn, yielding values val1, …, valn then create an event with bindings fieldi
=
vali - fields may appear in duplicate, however stupid that may seem; if two values are mapped to the same field, only the last one will be kept
- synthetic events can be posted using
inject_event
, provided themetaevent
module is loaded - Typing:
- Requires: each expri is of the type of fieldi, as given in its respective module
- Yields:
event
- evaluate expr1, …, exprn, yielding values val1, …, valn then create an event with bindings fieldi
- event enrichment: expr
+ .{
field1=
expr1,
…,
fieldn=
exprn}
create a synthetic event- evaluate expr to an event evt, evaluate expr1, …, exprn, yielding values val1, …, valn then append the indicated bindings fieldi
=
vali to evt - this is non-destructive, and creates a new synthetic event
- fields may appear in duplicate, however stupid that may seem; if two values are mapped to the same field, only the last one will be kept; in particular, this allows one to hide field values from evt and replace them with new values
- synthetic events can be posted using
inject_event
- expr can be obtained as a previously synthesized event, or using
current_event
- Typing:
- Requires: expr
: event
each expri is of the type of fieldi,
as given in its respective module - Yields:
event
- Requires: expr
- evaluate expr to an event evt, evaluate expr1, …, exprn, yielding values val1, …, valn then append the indicated bindings fieldi
- database expressions
- You should understand that all Orchids databases are applicative (non-destructive): you do not modify a database, add a tuple to a database, delete tuples from a database; instead, you build new databases from old, using the empty database
nothing
, singleton databases, database collections, as well as database unions (+
) and differences (-
) - empty database
nothing
- of type
db[*]
, convertible to any actual database typedb[
type1,…,typen]
- of type
- singleton database
{{
expr1, …, exprn}}
- of type
db[
type1,…,typen]
, where expr1 : type1, …, exprn : typen - contains just one tuple
- of type
- database collection:
for
db_pattern [and
db_pattern]* [{ statement* }] [collect
expr]- where db_pattern ::=
expr1, ..., exprn
in
expr - computes a generalized join of the databases given at the right of the
collect
keyword: for each tuple in the generalized join, build a database as given after thecollect
keyword, finally compute the union of all the computed databases (see examples below);
if thecollect
keyword is absent, return the empty databasenothing
- if the optional block { statement* } is present, execute it for each matching list of db_pattern
- this is non-destructive, and creates new databases
- Example 1:
for User, Id, Euid in $mydb collect {{User, Euid}}
builds a new database from$mydb
where the middle field (Id
) has been removed; this is an example of projection: for each tupleUser, Id, Euid
in$mydb
, we build a tuple containing justUser, Euid
, and take the union of all those tuples - Example 2:
for "Bill", Id, Euid in $mydb collect {{Id, Euid}}
builds a new database from$mydb
of those tuples whose first field matches the string"Bill"
exactly: this is an example of filtering. - Example 3:
for User, Service in $jobs and Service, Manager in $mgmt
collect {{User, Manager}}
builds a new database of pairsUser, Manager
such that the tupleUser, Service
is in$jobs
andService, Manager
is in$mgmt
for some valueService
: this is an example of a join (followed by projection, since we discardService
) - Example 4 (more involved):
for User, Pid, $epid in $mydb + $myotherdb
)
and Perm, Pid in $perm_db
collect ( {{Pid*128+Perm, User + " authorized"}} + {{Perm, "denied"}}
computes the union of the two databases$mydb
and$myotherdb
, then looks for all triples in it where the third field is equal to$epid
(obtaining the first and second fields inUser
andPid
respectively),
then does a join with$perm_db
on the value of the logical variablePid
,
and for each set of valuesUser
,Pid
,Perm
thus found, collects the two tuples computed asPid*128+Perm, User + " authorized"
and{{Perm, "denied"}}
(this is a fancy formula meant to illustrate what we can do with database collections, but has no practical use a priori)
- where db_pattern ::=
- You should understand that all Orchids databases are applicative (non-destructive): you do not modify a database, add a tuple to a database, delete tuples from a database; instead, you build new databases from old, using the empty database