• No results found

4.2 Pattern Matching and Transform

4.2.1 Pattern

Our analyser has been built in with several patterns, including while-loop, while-loop increment, while-loop decrement and append array patterns.

Definition 4.5 (Symbol Set) Let VARS be a set of symbols (variables and values).

Definition 4.6 (While-Loop Pattern) Function func is said to satisfy a while- loop pattern if func contains a while-loop structure, where the loop variable V initialises to INIT value, and the loop condition has a loop comparator OP and loop bound B .

64 The form of while-loop pattern is:

hV i = hINIT i; // Initialise loop variable V while hV i hOPi hBi: // Loop condition

hBODY not assigning to/updating V and not changing Bi hUpdate Vi

where variable V keeps track of the loop counter; expression INIT denotes the initial value of loop variable V ; OP is the comparing operator of loop condition; expression B denotes the loop bound; BODY represents a sequence of code inside loop body and does not update loop variable V nor loop bound B . Note expression INIT and B do not contain or update loop variable V .

A while-loop can be categorised as either an incremental or decremental while- loop pattern by the value of loop update. With the information of loop update and loop bound, we can estimate the number of loop iterations loop iters(V ) described as follows.

Definition 4.7 (Incremental While-loop Pattern) Function func is said to satisfy a while-loop increment loop if func is matched with while-loop pattern and the loop variable V is incremented by one in each iteration. The form of incremental while-loop pattern is:

hV i = hINIT i // Initialise loop variable while hV i hOPi hBi:// Loop condition

hBODY not updating V or Bi

hV i = hV i + 1 // Loop variable must be increased by one

where OP can only be< or≤; expression B and INIT are taken before entering the loop. The number of loop iterations loop iters(V ) is

loop iters(V ) =        B− INIT, OP is < B− INIT + 1, OP is ≤

Definition 4.8 (Decremental While-loop Pattern) Function func is said to satisfy a while-loop decremental loop if func is matched with while-loop pattern

and the loop variable is decremented by one in each iteration. The form of decremental while-loop pattern is:

hV i = hINIT i // Initialise loop variable while hV i hOPi hBi:// Loop condition

hBODY not updating V or Bi

hV i = hV i − 1 // Loop variable must be decreased by one

where OP can only be> or≥; expression B and INIT are taken before entering the loop. The number of loop iterations loop iters(V ) is

loop iters(V ) =        IN IT − B, OP is > IN IT − B + 1, OP is ≥

In some cases, the while-loop can be used to build up and extend an ar- ray dynamically to accommodate new array items by using function append . Function append is a standard system library function and makes a copy of input array, puts a new item into its last and returns the new array, as shown in the following Whiley program.

1 // Copy array ’items’ to ’nitems’ and append ’item’ to ’nitems’ 2 function append(byte[] items, byte item) -> (byte[] nitems) 3 ensures |nitems| == |items| + 1:

4 nitems = [0b; |items|+1]//Create an array filled in 0 (length: |items|+1) 5 int i = 0

6 while i < |items|: 7 nitems[i] = items[i] 8 i = i + 1

9 nitems[i] = item 10 // Return the new array 11 return nitems

Listing 4.6: Function append Whiley program

The above loop appends a fixed number of items (1 or more items) to the array every iteration. In this case, there is a linear relation between the number of array elements and the loop iterations. As such, we can express the length of such an array in terms of the number of loop iterations executed.

We propose append array pattern to identify such an array manipulation which calls function append to add one item to the array within a while-loop, and to give an estimate of the array size before the loop executed, so that we can allocate the necessary memory space for the target array.

66

Definition 4.9 (Append Array Pattern) Function func is said to satisfy an append array pattern if func matches with incremental or decremental while- loop pattern, as well as an output array variable ARR. Also, function append is called to add one item to array ARR per loop iteration.

The form of append array pattern with incremental while-loop is:

hARRi = [hX i; 0 ] // Initialize ARR with an empty array hV i = hINIT i

while hV i hOPi hBi:

hS0 not updating V, B or ARRi

hV i = hV i + 1 // Increment loop variable by one hS1 not updating V, B or ARRi

hARRi = append(hARRi, hitem1i) // Append item1 to array ARR

...

hSn not updating V, B or ARRi

hARRi = append(hARRi, hitemni)// Append itemn to array ARR

hSn+1 not updating V, B or ARRi

Or the form of append array pattern with decremental while-loop is

hARRi = [hX i; 0 ] // Initialize ARR with an empty array hV i = hINIT i

while hV i hOPi hBi:

hS0 not updating V, B or ARRi

hV i = hV i − 1

hS1 not updating V, B or ARRi

hARRi = append(hARRi, hitem1i)// Append item1 to array ARR

...

hSn not updating V, B or ARRi

hARRi = append(hARRi, hitemni)// Append itemn to array ARR

hSn+1 not updating V, B or ARRi

ARR denotes the loop variable. S0, S1, . . . Sn+1 each represents some state-

ments that do not contain or update loop variable V or array variable ARR. item1, . . . itemn denotes an array item that is appended to the last.

n items to array ARR. Thus, array ARR grows linearly with the number of function append calls and the number of loop iterations. And we can estimate the size of array ARR, denoted by arr capacity(ARR):

arr size(ARR) = loop iters(V )× n

where n is the number of function append executed in a loop iteration and loop iters(V ) represents the number of loop iterations.

With above definition, we can use append array pattern to pre-allocate the array with an estimate of array size before the execution, so that we can avoid slow array appending but use efficient array update to improve the program efficiency.

Definition 4.10 (Null Pattern) Function func is said to be a null pattern if func is not matched with any while-loop pattern.

The pattern matching procedure is straight-forward and described as follows. Given a function, the pattern matcher attempts to iterate each of our patterns and construct the pattern with the code of function. If the pattern can be built up successfully, then the function is matched with the pattern.

As our patterns is inherited from while-loop, we can conduct the procedure hierarchically. That is, we start with the while-loop pattern first and check the function matches it. If so, then we can move on to incremental or decremental while-loop, and even array append until we find the pattern at the deepest level. If no pattern is found, then NULL pattern is returned.