Loop evaluation

I would like to know how loop exit conditions in Systemverilog are evaluated.
For example, if I have a for loop

for (idx = 0; idx < queue.size();idx++)

Now within this loop, if I delete entries in the queue, would the compiler check size for every iteration or just once.

My initial hunch was that this is a static evaluation by the compiler and it would loop queue.size() times, as evaluated initially.
But I wrote a small piece of code and looks like compiler evaluates queue.size() for every iteration.

Below is the code:

module x;

integer Q[$] = { 1,2, 3, 5, 6, 7, 8, 9, 10};

initial begin
  for (int idx = 0; idx <= Q.size(); idx++) begin
    $display("idx %d val %d size %d", idx, Q[idx], Q.size());
    Q.delete(idx);
  end
end
endmodule

Below is the output:

idx 0 val 1 size 9
idx 1 val 3 size 8
idx 2 val 6 size 7
idx 3 val 8 size 6
idx 4 val 10 size 5

Can anyone provide more insight including any LRM section reference?

Pls use Q.size() in loop carefully.
As you see, Q.size() is changed for every iteration.
The following methods are recommended,
1.


  for (int idx = 0; idx <= Q.size(); idx++) begin
    $display("idx %d val %d size %d", idx, Q[idx], Q.size());
  end
  Q.delete();


  while (Q.size()) begin
    $display("idx %d val %d size %d", idx, Q[idx], Q.size());
    Q.delete(idx);
  end

Note that for repeat loops the expression is evaluated only once at the beginning of the loop, although the LRM doesn’t explicitly say this.

In reply to sbellock:

Note that for repeat loops the expression is evaluated only once at the beginning of the loop, although the LRM doesn’t explicitly say this.

Thanks. So, I assume, for other loop types, this is done at the start of each iteration.

In reply to verif_learner:

Correct. I’ve noticed that when Verilog / SystemVerilog borrows concepts from C it assumes the reader is already familiar with how C works, so that the LRM isn’t as explicit as the C standard. For comparison, the C standard specifies for-loops as:

The statement
for ( clause-1 ; expression-2 ; expression-3 )
behaves as follows: The expression expression-2 is the controlling expression that is evaluated before each execution of the loop body. The expression expression-3 is evaluated as a void expression after each execution of the loop body. If clause-1 is a declaration, the scope of any identifiers it declares is the remainder of the declaration and the entire loop, including the other two expressions; it is reached in the order of execution before the first evaluation of the controlling expression. If clause-1 is an expression, it is evaluated as a void expression before the first evaluation of the controlling expression. Both clause-1 and expression-3 can be omitted. An omitted expression-2 is replaced by a nonzero constant.