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?
Related
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.
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;
The intuitive answer would be that the loop is never entered. And this seems to be case in all tests I could come up with. I'm still anxious and always test it before entering the loop.
Is this necessary?
No, it is not necessary.
The documentation clearly states :
for counter := initialValue to finalValue do statement
or:
for counter := initialValue downto finalValue do statement
...
If initialValue is equal to finalValue, statement is executed exactly once. If initialValue is greater than finalValue in a for...to statement, or less than finalValue in a for...downto statement, then statement is never executed.
There is no need for anxiety.
If we want to examine further what happens, let's make a few examples. Consider first :
program Project1;
{$APPTYPE CONSOLE}
var
i : integer;
begin
for i := 2 to 1 do WriteLn(i);
end.
This produces a compiler hint:
[dcc32 Hint] Project1.dpr(6): H2135 FOR or WHILE loop executes zero times - deleted
So the compiler will simply throw away a loop with constants that produce no loop iterations. It does this even with optimizations turned off - no code is produced for the loop at all.
Now let's be a bit more clever :
program Project1;
{$APPTYPE CONSOLE}
var
i, j, k : integer;
begin
j := 2;
k := 1;
for i := j to k do WriteLn(i);
end.
This actually compiles the loop. The output is as below:
Project1.dpr.8: for i := j to k do WriteLn(i);
004060E8 A1A4AB4000 mov eax,[$0040aba4] {$0040aba4 -> j = 2}
004060ED 8B15A8AB4000 mov edx,[$0040aba8] {$0040aba8 -> k = 1}
004060F3 2BD0 sub edx,eax {edx = k - j = -1}
004060F5 7C2E jl $00406125 {was k-j < 0? if yes, jmp to end.}
004060F7 42 inc edx {set up loop}
004060F8 8955EC mov [ebp-$14],edx
004060FB A3A0AB4000 mov [$0040aba0],eax
00406100 A118784000 mov eax,[$00407818] {actual looped section}
00406105 8B15A0AB4000 mov edx,[$0040aba0]
0040610B E8E8D6FFFF call #Write0Long
00406110 E8C3D9FFFF call #WriteLn
00406115 E8EECCFFFF call #_IOTest
0040611A FF05A0AB4000 inc dword ptr [$0040aba0] {update loop var}
00406120 FF4DEC dec dword ptr [ebp-$14]
00406123 75DB jnz $00406100 {loop ^ if not complete}
Project1.dpr.9: end.
00406125 E88EE1FFFF call #Halt0
So, the very first thing a loop does is to check whether it needs to execute at all. If the initial is greater than the final (for a for..to loop) then it skips straight past it entirely. It doesn't even waste the cycles to initialize the loop counter.
There are some edge-cases in which you may be surprised to discover that the code does unexpectedly enter the loop. And still other cases where you may be tempted to pre-check whether to call the loop. But before I get into those details, I want to try impress on you the importance of not pre-checking your loop with an if condition.
Every line of code, no matter how easy to understand draws attention. It's more to read and more to confirm is correct. So if it's not important, or if it's technically redundant: it's best left out.
A for loop is conceptually translated as follows:
Initialise loop index to starting value.
If iteration constraint is valid (e.g. Index <= EndValue in case of forward loop):
Perform iteration (code within loop block/statement)
Perform loop control operations (increment loop index)
Repeat 2
Otherwise continue at first instruction after loop.
The way in which Step 2 is checked, makes an extra if condition before the loop completely redundant.
So if you (or another developer) is later maintaining code with a redundant if condition, they're left to wonder:
Is the line correct?
It seems redundant; is there a special condition it's trying to handle?
If it currently serves no purpose, perhaps it was intended to prevent calling the loop on a different condition?
In simple case, redundant lines of code can create some confusion. In more complex cases, they can result in whole new sections of irrelevant code being developed; that tries to cater for irrelevant scenarios implied by legacy redundant code.
Recommendation: Stamp out redundant code as much as possible. Including redundant pre-checks for "should the loop execute at all".
The most important benefit of stamping out redundant code is that: it correctly draws attention to peculiar cases whenever special handling actually is required.
There are 2 potential pitfalls, and the first is the more dangerous one as it deals with implicit type conversion. So it may not always be easy to detect. The following code was tested on rextester using fpc, but I have verified the same issue on Delphi 2007 / 2009 in the past.
//fpc 2.6.2
program UnexpectedForIteration;
{$MODE DELPHI}
{ Ensure range-checking is off. If it's on, a run-time error
prevents potentially bad side-effects of invalid iterations.}
{$R-,H+,W+}
var
IntStart, IntEnd, IntIndex: Integer;
UIntStart, UIntEnd, UIntIndex: Cardinal;
IterCount: Integer;
begin
Writeln('Case 1');
IntStart := High(Integer) - 1;
IntEnd := -IntStart;
UIntStart := Cardinal(IntStart);
UIntEnd := Cardinal(IntEnd);
{This gives a clue why the problem occurs.}
Writeln('From: ', IntStart, ' To: ', IntEnd);
Writeln('From: ', UIntStart, ' To: ', UIntEnd, ' (unsigned)');
Writeln('Loop 1');
IterCount := 0;
for IntIndex := IntStart to IntEnd do Inc(IterCount);
Writeln(IterCount);
Writeln('Loop 2');
IterCount := 0;
{ The loop index variable is a different type to the initial &
final values. So implicit conversion takes place and:
IntEnd **as** unsigned is unexpectedly bigger than IntStart }
for UIntIndex := IntStart to IntEnd do Inc(IterCount);
Writeln(IterCount, ' {Houston we have a problem}');
Writeln();
Writeln('Case 2');
UIntStart := High(Cardinal) - 2;
UIntEnd := 2;
IntStart := Integer(UIntStart);
IntEnd := Integer(UIntEnd);
{This gives a clue why the problem occurs.}
Writeln('From: ', UIntStart, ' To: ', UIntEnd);
Writeln('From: ', IntStart, ' To: ', IntEnd, ' (signed)');
Writeln('Loop 3');
IterCount := 0;
for UIntIndex := UIntStart to UIntEnd do Inc(IterCount);
Writeln(IterCount);
Writeln('Loop 4');
IterCount := 0;
{ The loop index variable is a different type to the initial &
final values. So implicit conversion takes place and:
UIntStart **as** signed is unexpectedly less than UIntEnd }
for IntIndex := UIntStart to UIntEnd do Inc(IterCount);
Writeln(IterCount, ' {Houston we have a problem}');
end.
The output is as follows:
Case 1
From: 2147483646 To: -2147483646
From: 2147483646 To: 2147483650 (unsigned)
Loop 1
0
Loop 2
5 {Houston we have a problem}
Case 2
From: 4294967293 To: 2
From: -3 To: 2 (signed)
Loop 3
0
Loop 4
6 {Houston we have a problem}
In many cases the problem is resolved by ensuring the same types are used for loopIndex, initialValue and finalValue. As this means there won't be an implicit type conversion, and the loop will reliably iterate as the initialValue and finalValue would suggest.
It would be easier if the compiler emits appropriate warnings for implicit type conversion in for loops. Unfortunately fpc didn't; I don't recall whether Delphi 2007/2009 does; and have no idea whether any recent versions do.
However, the preferred approach would be to favour container iteration syntax (pushing responsibility for 'correct' iteration on the enumerators). E.g.: for <element> in <container> do ...;. This should not iterate empty containers provided the enumerator's methods are implemented correctly.
The only time I'd say a pre-check is worth considering is:
when for in is not feasible for some reason
and the loop index needs to be zero-based
and support large unsigned integers (High(Integer) < index < High(Cardinal))
because this leaves no space for a reliable sentinel less than all possible initial values.
Even in this case, consider using an Int64 loop index instead of if (initialValue <= finalValue) then for ....
The second pitfall involves what I would in any case consider to be a design flaw. So the problem can be avoided entirely by rather being aware of this design consideration. It is demonstrated in code that looks as follows:
if Assigned(AnObject) then
for LIndex := 0 to AnObject.Count - 1 do ...;
In this case the if condition may in fact be necessary as a result of dubious design. Certainly, if AnObject hasn't been created, you do not want to access its Count property/method. But the dubious aspect of the design is the fact that you're uncertain whether AnObject exists. Yes, you may have employed a lazy-initialisation pattern. But it doesn't change the fact that in the above code, there's no way to differentiate between: "zero iterations" because AnObject doesn't exist or because AnObject.Count = 0.
I'd like to point out that when code has many redundant if Assigned(AnObject) then (or similar) lines, it leads to one of the problems I described in section 1. Local code caters for 2 possibilities. And by extension, client code also caters for 2 possibilities. And by induction, this problem eventually leaks throughout the code-base.
The solution is to first and foremost limit the cases where existence of AnObject is uncertain.
It's much easier to ensure an empty object with Count = 0 is guaranteed to be created (typically only affecting a small number of places in code).
It's far more work to deal with the ripple effects of a large number of places where the object might not exist yet; yielding 2 possible states and code paths.
If lazy-initialisation is required, try to ensure the code surface where existence is optional is kept as small as possible.
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.
I am experimenting with the ability to dynamically invoke procedures or functions that reside in a function table. The specific application is a DLL that exports a pointer to a function table together with information on the number of arguments and types. The host application then has the ability to interrogate the DLL and call the functions. If they were object methods I could use Rtti to invoke them but they are normal procedures and functions. The DLL has to export normal function pointers not objects because the DLL could be written in any language including C, Delphi etc.
For example, I have a record declared and filled out in a DLL:
TAPI = record
add : function (var a, b : double) : double;
mult : function (var a, b : double) : double;
end;
PAPI = ^TAPI;
I retrieve the pointer to this record, declared as:
apiPtr : PAPI;
Assume I also have access to the names of the procedures, number of arguments and argument types for each entry in the record.
Assume I want to call the add function. The function pointer to add will be:
#apiPtr^.add // I assume this will give me a pointer to the add function
I assume there is no other way other than to use some asm to push the necessary arguments on the stack and retrieve the result?
First question, what is the best calling convention to declare the procedure as, cdecl? Seems easiest for assembling the stack before the call.
Second question, are there any examples online that actually do this? I came across http://www.swissdelphicenter.ch/torry/showcode.php?id=1745 (DynamicDllCall) which is close to what I want but I simplified as below, it now returns a pointer (EAX) to the result:
function DynamicDllCall(proc : pointer; const Parameters: array of Pointer): pointer;
var x, n: Integer;
p: Pointer;
begin
n := High(Parameters);
if n > -1 then begin
x := n;
repeat
p := Parameters[x];
asm
PUSH p
end;
Dec(x);
until x = -1;
end;
asm
CALL proc
MOV p, EAX <- must be changed to "FST result" if return value is double
end;
result := p;
end;
but I can't get it to work, it returns a value for the first parameters instead of the result. Maybe I have the calling convention wrong or maybe I misunderstand how to retrieve the result in EAX.
I call DynamicDllCall as follows:
var proc : pointer;
parameters: array of Pointer;
x, y, z : double;
p : pointer;
begin
x:= 2.3; y := 6.7;
SetLength(parameters, 2);
parameters[0] := #x; parameters[1] := #y;
proc := #apiPtr^.add;
p := DynamicDllCall(proc, Parameters);
z := double (p^);
Any advice gratefully received. I appreciate that some may feel this isn't the way one should go about doing this but I am still curious if it is at least possible.
Update 1 I can confirm that the add function is getting the correct values to do the addition.
Update 2 If I change the signature of add to:
add : function (var a, b, c : double) : double;
and I assign the result to c inside add, then I can retrieve the correct answer in the parameters array (assuming I add one more element to it, 3 instead of 2). The problem therefore is that I misunderstand how values are returned from functions. Can anyone explain how functions return values and how best to retrieve them?
Update 3 I have my answer. I should have guessed. Delphi returns different types via different registers. eg integers return via EAX, double on the other hand returns via ST(0). To copy ST(0) to the result variable I must use "FST result" rather than "MOV p, EAX". I least I now know it is possible in principle to do this. Whether it is a sensible thing to do is another matter I must now think about.
This is an XY problem: You want to do X, and, for whatever reason, you've decided Y is the solution, but you're having trouble making Y work. In your case, X is call external functions via pointers and Y is manually push parameters on the stack. But to accomplish X, you don't really need to do Y.
The expression #apiPtr^.add will not give you a pointer to the function. It will give you a pointer to the add field of the TAPI record. (Since add is the first member of the record, the address of that field will be equal to the address held in apiPtr; in code, Assert(CompareMem(#apiPtr, #apiPtr^.add, SizeOf(Pointer)).) The add field holds a pointer to the function, so if that's what you want, just use apiPtr^.add (and note that the ^ is optional in Delphi).
The best calling convention to use is stdcall. Any language that supports exporting DLL functions will support that calling convention.
You don't need assembler or any other tricky stack manipulation to call your functions. You already know the function's type because you used it to declare add. To call the function pointed to by that field, simply use the same syntax as for calling an ordinary function:
z := apiPtr.add(x, y);
The compiler knows the declared type of the add field, so it will arrange the stack for you.
This is a hard problem to solve. One way to dynamically access methods in a DLL at runtime would be to use a foreign function interface library such as libffi, dyncall or DynaCall(). None of these however have yet been ported to the Delphi environment.
If the application is to interface a set of methods in a DLL together with Rtti information provided by the DLL and expose them to a scripting language such as Python, one option is to write Delphi code that inspects the DLL and writes out a ctypes compatible script which can be loaded into an embedded Python interpreter at runtime. So long as one defines before hand a limited but sufficient set of types that the DLL methods can handle, this is a practical solution.