Cobra Inline Programs associative arrays


associative arrays


An associative array is identified by a basename and an index in square brackets. Associative arrays can store any type of result, a value, a string, or a token reference, and they can be indexed with any type of index, as well as with multiple indices separated by commas.

Scope Rules

There are only two levels of scope in inline programs: global and function local, depending on the first time that the associative array name is encountered.
  • This means that if an array name is first seen inside a function call, that instance will be function local. When the same name is later also seen outside all functions, this will create a new global instance of the array. If now the same function from before is called again, the global instance of the name will now be used.
  • To avoid potential confusion, variables and associative arrays can be declared with global scope with the notation:
    	global varname;		# declare varname as a global scalar variable
    	global arrayname[];	# declare arrayname as a global associative array
    But, make sure that this is the first occurrence of the name that is encountered in a script execution.

Some Examples

	basename[index] = value;
	basename[.txt , .len] = .;

	X[.txt] = .mark;
	Y[.mark] = .fnm;
	Z[.fnm] = .;
	Z[.fnm , 0, "foo"] = 42;
A new value (and type) may overwrite an old one at any time.

Associative array elements that store a token reference cannot be indexed directly with a token field. To do so the element must first be assigned to a regular token reference variable, for instance as follows:

	Z[.fnm] = .;
	Z[.fnm].mark;	# gives a syntax error
	q = Z[.fnm];	# is okay
	print q.mark ":" q.txt "\n";
The number of elements in an associative array can be determined with the size function:
	v = size(Z);
Normally the elements of an associative array are retrieved simply by reference, e.g., as in:
	x = Z["foo"];
If the array element evaluated does not exist, the result will be zero (or depending on context the empty string).


We can iterate over the elements of an associate array with a for statement, as follows:
	for (i in Z)
	{	print i.mark ": " i.txt " = " Z[i.txt] "\n";
The loop variable i is treated as a token reference, to allow us to refer to two separate parts of the indices that are returned. The first part is the index value itself, which is given as a string in the text field: i.txt. The second part is the i.mark field, which holds a numeric index of the array element. For technical reasons the number in the .mark field is one higher than the actual index value, which starts at zero. An array element can also be retrieved directly with a numeric index with a predefined function. For instance,
	v = retrieve(Z, 0);
retrieves the first element of Z. The ordering of the elements in an associative array depend on internal implementation details, and is not related to the order in which the elements were added to the associative array.

Predefined Functions

There are four different support functions for associative arrays:
	retrieve(A, n)	-- retrieves the nth element of associative array A
	size(A)		-- returns the number of elements stored in array A
	unset A[el]	-- remove associative array element A[el]
	unset A		-- remove variable or array A


Building large associative arrays can incur a runtime penalty, both for adding new elements, retrieving existing elements, or removing elements. Therefore it is typically best to keep the arrays small, and to remove them as soon as feasible, when they no longer hold relevant information.

Also in multi-core checks, the process of unifying the various parts of the associative arrays build by the different cores can be time consuming. In those cases it can be much faster to remember relevant token reference by tagging them in the relevant .mark fields, which can later very quickly be collected in a single pass over all the tokens.

Also see predefined functions, for more detail.

Inline Programs
(Last Updated: 13 November 2020)