modifying a return variable in dafny - dafny

so I have a method in dafny that takes in an array a, and returns the sorted version, b. In my code, b := a, and then the in-place insertion-sort happens on b. However, whenever I modify b, I get the error that an "assignment may update an array element not in the enclosing context's modifies clause". I am assuming this is because I haven't told dafny I will be in-place modifying b. How do I fix this?

Arrays in Dafny are references to array elements. (This is also the case in C, Java, C#, and various other languages.) The assignment b := a; copies the reference, but does not copy the elements. You have two choices.
One choice is to create a new array that eventually will hold the sorted elements. To do that, allocate a new array:
b := new int[a.Length];
If you also want to copy the elements of a into the new array b, then do:
b := new int[a.Length](i requires 0 <= i < a.Length reads a => a[i]);
or
b := new int[a.Length];
forall i | 0 <= i < a.Length {
b[i] := a[i];
}
Under this choice, the caller will still have a reference to the original array, which will be intact. Through the method's out-parameter, the caller will also get a reference to the new (sorted) array.
The other choice is to modify the original array. Since this affects the caller, you need to write a specification that tells the caller about this. That's done by adding
modifies a
to your method's specification. Under this choice, there's no reason to declare the out-parameter b, since there is only one array and a references it.

Related

Removing part of condition in some cases

Is there a way to remove part of condition in IF statement depending if I need it or not. Next code is example, because in my code there are a lot of user defined functions and procedures in my language:
IF A THEN
Q := TQuery.Create(Application);
IF B AND C AND D AND E AND Q.FieldByName('Example').AsInteger = 1 then
BEGIN
...
END
So, let's say after creating TQuery that I have imported some data into it (I didn't write that part of code here). Is there a way to remove part with Q in the second IF statement if the Q wasn't created (because the condition A was not satisfied) or do I have to writhe the whole IF statement again just without Q part?
I was thinking using something like CASE to check if Q is created and if it is not, just to skip that part of sentence. If it is possible, how can I skip it?
Quick and dirty way
IF B AND C AND D AND E AND (NOT A OR Q.FieldByName('Example').AsInteger = 1) then
As a note, try to keep your if conditions simpler.
EvaluationRequested := A AND C ...
QueryNeedsAval := NOT A OR ...
if EvaluationRequested AND QueryNeedsAval then
begin
...
end;

Is it possible to turn a statement into a expression?

In C, you can assign two variables in one line with
b = a = sqrt(10);
In Delphi
b := a := Sqrt(10);
is not allowed.
With IfThen, there is an "alternative" for the ternary operator ?: as discussed in Delphi - Equivalent to C#'s ternary operator? In summary, IfThen doesn't seem absolutely necessary.
So maybe there is also something like this:
function AssignAndReturn(var LHS: Integer; RHS: Integer): Integer;
begin
LHS := RHS;
Result := RHS;
end;
(...)
var
a, b: Integer;
begin
b := AssignAndReturn(a, Round(Sqrt(10)));
I'm not trying to "make everything look like C". I just noticed, that sometimes it would be nice to "reuse" the right hand side of an assignment in the same line again. (See Lazarus/Free Pascal: How to improve coding style (to avoid using endless loop) of a while loop whose boolean expression is reassigned every pass for example.)
An assignment statement is not an expression. It does not, and will never, yield a value. The only way to assign to multiple variables in one statement is via a function.
Based on this question and your previous question I would say that you are mistaken in trying to fight against the language. Code into the language you are using. In C you might write
b = a = sqrt(10);
But in Pascal the language wants you to write it like this
a := sqrt(10);
b := a;
Do it this way. Don't create obscure functions just so that you can cram it all onto a single line. The two lines above could not be clearer to read. Stop trying to force other languages into Pascal. They don't fit.
The short answer is:
No. What you want is not possible. And arguably would be of little if any benefit in Delphi.
First, let's discuss a more practical example. To be frank, a = b = f(x); is a rather poor example.
It's rare that you arbitrarily want the same value assigned to 2 variables.
Order of operation above has to break the left to right convention otherwise it would first resolve a = b then ? = f(x).
So there's little justification to favour that over b = f(x); a = b;.
Basically it's good for byte count (code golf) not readability.
So instead, let's consider the following, more practical scenario:
//Option 1
if ((b = f(x)) > 42)
//use b
There's no Delphi equivalent to the above, but it's at least as readable/maintainable to write:
//Option 2
b := f(x);
if (b > 42) then
//use b
There is another option to consider; especially if Option 1 is sitting in the middle of a larger function. Remember small functions are more maintainable and easier for a compiler to optimise. So consider:
//Option 3
...
ProcessRule42(f(x));
...
//Where Rule42 is is implemented as:
procedure ProcessRule42(b: Integer);
begin
if (b > 42) then
//use b
end;
Delphi doesn't really seem to be suffering due to not being able to write: if (b := f(x)) > 42 then //use b.
Is there any real benefit to Option 1?
If the Option 2 is at least as good, why would one ever bother with Option 1. The benefit is seen when you consider scoping rules.
//b does not exist
if ((var b = f(x)) > 42) {
//use b
}
//b does not exist
// Using the Delphi approach, this becomes:
//b does not exist
var b = f(x);
if (b > 42) {
//use b
}
//b still exists
Delphi simply does not have the same scoping concerns. Delphi variables are all declared at the beginning of the method, and available for the whole method.
Conclusion
This brings us back to what others have been trying to explain. Delphi is a different language with slightly different approaches to some problems. While I applaud you for examining other options and considering what concepts can be borrowed from other languages: be careful of trying to force-fit some concepts where they don't belong.
If you break too many Delphi paradigms, your code may become unnecessarily difficult for Delphi programmers to maintain.

How to call a procedure with a rowtype literal as parameter in PL/SQL?

Lets say I have a table and a procedure that accepts one argument of the tables rowtype:
CREATE TABLE t (a NUMBER, b NUMBER);
CREATE PROCEDURE p (x t%ROWTYPE) IS
BEGIN
NULL;
END;
Can I call that procedure using a rowtype literal, that is without explicitly creating a rowtype variable (or at least not explicitly listing and assigning every field of it)? The two following approaches both generate the below error:
p(1, 2);
p((1, 2));
PLS-00306: wrong number or types of arguments in call to 'P'
You could also construct the record from a cursor loop:
for r in (
select 1, 2 from dual
)
loop
p(r);
end loop;
Unfortunately PL/SQL records are just simple structures and don't come with constructors as object types do. (I wish they did.)
This is not an optimal solution, since it (a) requires the creation of a variable and (b) isn't very pretty. But at least it works:
DECLARE
x t%ROWTYPE;
BEGIN
SELECT 1, 2 INTO x FROM dual;
p(x);
END;
I am still interested in better solutions.

CompareMem does not seem to work when using a value that came from an array

So I have a test case in my program
procedure MemCheck<T>(x, y : T);
var
a, b : T;
vals : array of T;
c : T;
begin
a := x;
b := y;
c := a;
SetLength(vals, 4);
vals[0] := a;
vals[1] := a;
vals[2] := a;
vals[3] := a;
c := T(vals[2]); //c := a ; workes fine
Check
(
CompareMem(#c, #y, SizeOf(T)),
'Memory compare check'
);
end;
This test case fails and I'm not sure why
MemCheck<String>('a', 'a');
it works fine when I use
c := a ; instead of c := T(vals[2]);
You are passing string literals to MemCheck(). Since they are the same value, the compiler merges them together in the executable. So you are actually passing a single constant string literal to both the x and y parameters. String literals are read-only and have a reference count of -1. Assigning a string literal to a String variable copies the pointer to the memory block as-is without allocating new memory or incrementing the memory block's reference count.
Up to the point before you populate the vals array, your a, b, and c variables are just copies of the string literal pointer. They are all pointing at the same data block in memory. The System.StringRefCount() function confirms that they all return a reference count of -1, proving they are all pointing at a string literal.
In the statement vals[2] := a;, a is pointing at a string literal, so the RTL allocates a new String instance and copies the content of the string literal into the new memory block. a still has a reference count of -1, but vals[2] now has a reference count of 1, proving that an allocation was performed. The statement c := T(vals[2]); is then assigning an allocated String to a String variable, so the allocated data's reference count gets incremented. StringRefCount() confirms that c now has a reference count of 2.
CompareMem() then consequently fails, because you are comparing the value of the internal data pointer of two String variables that are pointing at two different memory blocks, so their pointer values are different and the comparison fails.
When you change the statement c := T(vals[2]); to c := a;, a is still pointing at the string literal in memory, so that pointer gets copied as-is into c without performing any allocation. Thus CompareMem() succeeds because now you are comparing the value of the internal data pointer of two String variables that are pointing at the same memory block, so the comparison succeeds.
So the real question is - why is the statement vals[2] := a; performing a new allocation instead of just copying the data pointer as-is like any other String := String; assignment?
The assignments a := x;, b := y; and c := a; are calling the System.#UStrLAsg() function, which permits a String pointing at a string literal to be assigned as-is to another String without performing an allocation.
The statement vals[2] := a; is calling the System.#UStrAsg() function instead, which always makes a new allocated copy when the source String is pointing at a string literal.
Why is the compiler choosing to use #UStrAsg() instead of #UStrLAsg() in the vals[2] := a; statement? That is just the way the compiler works when the left-hand side of the assignment is a String inside a dynamic array, rather than a standalone variable. If vals were a static array instead (vals: array[0..3] of String;), the compiler would choose to use #UStrLAsg() instead of #UStrAsg(), and CompareMem() would then succeed.
#UStrLAsg() is typically used when assigning a String to a local String, thus it is usually safe to allow a string literal to be used as-is.
#UStrAsg() is typically used when assigning a String to a global String, where a literal needs to be copied to avoid potential memory errors when the literal might exist in a DLL/Package that could be unloaded after the assignment.
So the compiler must be airing on the side of caution when assigning to a dynamic array as it does not know, or cannot assume, the lifetime of the String instances in the array.

Delphi 2006 - Assigning dynamic array function results

I had code with the basic constructs illustrated by the following:
type
TDynamicArray = array of double ;
var
a : TDynamicArray ;
function Func : TDynamicArray ;
var
b : TDynamicArray ;
begin
SetLength (B, 3) ;
b [0] := 0.0 ;
b [1] := 1.0 ;
b [2] := 2.0 ;
Result := b ; // note 1 -- should use Result := Copy (b, 0, Length (b))
end ;
begin
a := Func ; // note 2 -- should we (or could we) use a := Copy (Func, 0, Length (Func))
end.
It had been working fine until lately when the function started returning empty arrays. I then spot this which enlightens me to the fact that simple assignment isn't correct, I need to use Copy.
Two questions:
I realise I need 'Copy' on the line marked Note 1 to assign to the
function result. Do I need to use Copy also on the assignment of
the function result to array a (line Note 2)?.
Why did the compiler allow my construct and what was the compiled code actually
doing?
I realise I could try these things and see, but I'm a little spooked by the compiler letting questionable stuff through.
There is no reason to use Copy in either of those assignment statements. Normal assignment works fine. When you allocate b, the reference count of the array is 1. When you assign it to Result, the reference count becomes 2. (Personally, I'd just forego b and operate directly on Result from the start.) When the function returns, b goes out of scope and the reference count becomes 1 again. Finally, when the result is assigned to a, nothing happens because Result was actually an alias for a all along. Ultimately, you're left with one unique array, which should be exactly what you intended.
The compiler allowed your code because your code is fine. The compiler recognizes assignments between arrays just as it does assignments between strings and assignments between interface references, and it generates the right code to adjust the reference counts accordingly.
Using Copy would create an entire copy of the array, but you don't need that. Each time you think you need it, it's in a place where you would have immediately discarded the previous copy anyway. Why make a copy when you already have a perfectly good array ready for any use you want?

Resources