I'm trying to overwrite an array inside a method. The compiler is giving me the error "Error: LHS of assignment must denote a mutable variable".
method invalidSort(a : array<int>)
modifies a;
requires a != null;
ensures sorted(a[..]);
{
a := new int[0];
}
Am I staring myself blind and missing something or why does Dafny not allow this?
In Dafny, method parameters cannot be assigned to. You can use a local variable if you need to update the value internally.
For example,
var a' := new int[0];
If you want this new array to be available to the caller, you'll also need to return it.
return a';
All that said, if you're trying to write an in-place sorting method, then you don't need to do any of this. Just modify a in place.
a[0] := 0;
// ...
Related
I have a simple class with autocontracts in Dafny, that creates a new instance of itself.
But Dafny says that "call might violate context's modifies clause" when I call foo.Add() inside Bar method
I can't tell why I'm getting this error since the class does not have any attributes
Am I missing something?
class {:autocontracts} Foo {
predicate Valid()
constructor() { }
method Add() returns (b:bool)
method Bar() returns (fo:Foo)
ensures fresh(fo)
{
fo := new Foo();
var i := 0;
while(i < 3)
modifies fo
invariant fo.Valid()
{
var ret := fo.Add(); //call might violate context's modifies clause Verifier
i := 1 + i;
}
}
}
Dafny Version at VSCode
the installed Dafny version is the latest known: 3.9.0.41003 = 3.9.0
I think you might have oversimplified your example, because I'm not sure I understand your question.
I think the answer you are looking for is that you should delete the line
modifies fo
from the loop and add the line
invariant fresh(fo.Repr)
This fixes the error about violating the context's modifies clause.
The remaining error in the code you did not mention, but it has to do with the autocontracts postcondition for Bar, which is
this.Valid() && fresh(this.Repr - old(this.Repr))
This is doubly confusing because the Foo class has no fields, and the Bar method never mentions this. So one fix would be to make Bar a static method.
Alternatively, if in your original setting you need Bar to be non-static, then you can add the invariant
invariant this.Valid() && fresh(this.Repr - old(this.Repr))
to the loop to fix this second error.
For simple data types, you can use e.g.
object is String
to check whether an Object variable is of a more specific type.
But let's you have a List, but want to check if it is a List of Strings. Intuitively we might try
List list = ['string', 'other string'];
print(list is List<String>);
which returns false.
Similarly using the List.cast() method doesn't help, it will always succeed and only throw an error later on when using the list.
We could iterate over the entire list and check the type of each individual entry, but I was hoping there might be a better way.
There is no other way. What you have is a List<Object?>/List<dynamic> (because the type is inferred from the variable type, which is a raw List type which gets instantiated to its bound). The list currently only contains String objects, but nothing prevents you from adding a new Object() to it.
So, the object itself doesn't know that it only contains strings, you have to look at each element to check that.
Or, when you create a list, just declare the variable as List<String> list = ...; or var list = ...;, then the object will be a List<String>.
If you are not the one creating the list, it's back to list.every((e) => e is String).
Each element of a List may be of any type BUT IF YOU ARE SURE that all elements have the same type this approach may be useful
bool listElementIs<T>(List l) {
if (l.isEmpty) return true;
try {
if (l[0] is T) return true; // only try to access to check element
} catch (e) {
return false;
}
return false;
}
void main() {
List list = ['string', 'other string'];
print(listElementIs<String>(list)); // prints 'true'
print(listElementIs<int>(list)); // prints 'false'
}
I think a better way to do this is to be specific about your data types.
By specifying the types of variables, you can catch potential errors early on during the development process.
In addition, specifying the types of variables makes the code more readable and understandable.
Furthermore, specifying types can also improve the performance of your code, as the compiler can make certain optimizations based on the types of variables.
List<String> list = <String>['string', 'other string'];
print(list is List<String>); /// prints true.
You can use this linter rule to enforce it:
https://dart-lang.github.io/linter/lints/always_specify_types.html
In Delphi, suppose I have a method with a (much simplified) signature like this:
procedure abc( const prop1:string; const arg1:TValue; const prop2:string;
out arg2:TValue );
I'm building a TList<PPropValPair> of records like this using the parameters provided:
type
TPVPType = (ptIn, ptOut);
PPropValPair = ^TPropValPair;
TPropValPair = record
io : TPVPType;
prop : string; // property name
iVal : TValue; // input value
oVar : Variant; // <-- how to save for later use??? Variant? TValue?
end;
(On the face of it, this example looks silly. Again, it's quite simplified just to communicate the problem.)
At run-time, I want to stuff all of the input values ival (where io=ptIn) into each public property 'prop' in a class, call a class method, then extract the values of all public properites 'prop' (where io=ptOut) into oVar.
The input side is working fine using RTTI.
However, I need to somehow save a REFERENCE to the output vars in oVar so I can save the value of the associated properties after the class method has been called.
I'm not assigning anything to arg2 directly. Rather, I'm saving a reference to arg2 and assigning the value indirectly later on.
The trick is ... I don't want to have to do any additional annotations of the output parameters in abc(...).
In C++, you can declare a parameter as a 'reference' by prepending it with '&'. So in C++ terms this might be defined roughly as:
procedure abc( arg1 : TValue; &arg2 : TValue );
Later, you can refer to &arg2 and it's using a POINTER to the object. But in calling the function, you just say:
abc( somevar1, somevar2 );
somevar1 is passed by value, and somevar2 is passed by reference. Inside the function, I can save somevar2 in a reference var, then later on assign a value to it via the pointer (if it's a string) by saying &arg2ref = 'abc'.
I'm guessing there's a way to do this in Delphi, either with a Variant as the oVar type, or using RTTI, or something else. I just haven't figured out the magic combination of pieces yet. (I just don't use pointers very often in Delphi.)
Maybe I need to save a raw pointer in oVar along with the type (say, oType), and cast a value through the pointer to save the property's value?
I'm hoping someone here might have some clear ideas.
BTW, I'm using Delphi XE3.
Use a pointer. It doesn't have to (and indeed shouldn't) be a "raw" pointer. Use a typed pointer, PValue. Pass in a PValue to your function, and then store that in oVal, which you should also declare a a PValue. Use # to create a pointer, and ^ to dereference.
I would not recommend passing arg2 by reference. Although you can still use # on it to get a pointer to the original variable passed to abc, the reference parameter disguises the fact that the variable needs to remain available indefinitely. Instead, declare arg2 as PValue so it's more obvious to the caller that indirection is involved.
// declaration
procedure abc(...; arg2: PValue);
// call
abc(..., #somevar2);
right now iam trying to create some Stored Procedures for a HSQL-DB.
I want to create a new User and return the ID of the new User.
For example i tried it like this to create the Procedure.
create procedure test(out param int)
modifies sql data
begin atomic
set param = 1;
end;
=> Call it
declare param int ;
call test(param);
call param;
=> Error
dynamic parameter or variable required as INOUT or OUT argument
I can´t find the bug -.-
so long.
This is how you call the procedure:
declare param int;
call test(param)
call param
It looks the same, but each statement is executed separately!
I tried to make my code as simple as possible,but I failed at it.
This is my code:
class function TWS.WinsockSend(s:integer;buffer:pointer;size:word):boolean;
begin
dwError := Send(s,buffer,size,0);
// Debug
if(dwError = SOCKET_ERROR) then
begin
dwError := WSAGetLastError;
CloseSocket(s);
WSACleanup;
case (dwerror) of
//Case statement
else
LogToFile('Unhandled error: ' + IntToStr(dwError) + ' generated by WSASend');
end;
Exit(false);
end;
// if the size of the bytes sent isn't the expected one.
while(dwError <> size) do
dwError:= dwError + Send(s,Ptr(cardinal(buffer) + dwError),size-dwError,0);
Exit(true);
end;
The error is placed at
dwError:= dwError + Send(s,Ptr(cardinal(buffer) + dwError),size-dwError,0);
Error is "Constant object cannot be passed as var parameter"
I understand I need a variable,but isn't there a way I can do it without adding one more line?
When the compiler complains about the way you're passing a parameter, the first thing you need to know is what the parameter expects. Therefore, you should go look at the declaration of Send. If looking at the declaration doesn't immediately give you an idea of what to fix, then you need to include that declaration with the code you post in your question.
I suspect that this actually has nothing to do with incrementing a pointer. Instead, the compiler is complaining about the third parameter, where you are trying to pass the expression size-dwError. I guess the parameter is declared like this:
var buffersize: Word;
The function plans on providing a new value for that parameter — that's what var means — so the thing you pass to that parameter needs to be something that can receive a value. You can't assign a new value to the result of subtracting two variables.
Take a closer look at where the compiler complained about that line. Didn't it place the cursor somewhere near the third parameter? That's a clue that the problem is there.
Decrement size, and then pass it to the function.
Dec(size, dwError);
Inc(dwError, Send(s, Ptr(cardinal(buffer) + dwError), size, 0));
Why do you care about adding another line? Have you reached your quota for the day? Lines are cheap; don't be afraid to use two to express yourself when one won't do. Likewise for variables. When your code doesn't work, saving a byte or two doesn't matter at all.
At the very least, you should have added more lines in order to track down the source of the problem. When you have one line of code that's performing several independent calculations (such as getting a new pointer value, getting a new size, and calling a function), break the line into several separate pieces. That way, if there's a problem with one of them and the compiler complains, you'll know exactly which one to blame.
Correct, this will not work as written. When your dealing with var parameters, you have to build the parameter BEFORE passing it to the procedure/function. When a Var parameter is passed, the procedure is allowed to modify it. If you attempted to copy two variables together on the call, where would this result go?
The other issue is that dwError is not delcared. A class method does NOT have access to the data elements of the object the class defines. If you drop the class, then you will have access to the data elements, but will require that the class first be created.
You should only be using class methods in places where the input and output are completely contained within the method.
How are you allocating your buffer? Internally is it an array?
Sounds like Send has a format parameter (like send (const something;size:integer)
Workaround is using pchar (entirepointerexpression)[0]