On 10 Mar 2005 at 3:55, Waldek Hebisch wrote:
Prof A Olowofoyeku wrote:
On 9 Mar 2005 at 2:01, Waldek Hebisch wrote:
BTW, when I write:
bar := tfunc (foo());
then my copy of FPC (1.9.4 on Debian) still gives wrong result.
What it gives is the value of "foo", which, inside "foo", you assign the address of "baz" (i.e., foo returns the address of baz as an integer). That seems correct to me.
I do not know what your FPC is doing, but AFAICS my copy of FPC treats:
bar := tfunc (foo);
and
bar := tfunc (foo());
the same.
Yes (as does GPC (currently)).
Now, the first form is ambiguous, and what FPC is doing with this form is usefull and reasonable. IMHO the second form has only one possible meaning: empty parentheses mean that `foo' should be called and the _return value_ of `foo' should be converted and assigned to `bar'.
I am not sure. I think the second form is just as ambiguous as the first. The parentheses may simply signify that "foo" is a function/procedure as opposed to a variable (where parentheses should cause an error), in which case, it is no different from not using the parentheses. In neither case would I want a conversion of the return value of "foo". In both cases, I would want "bar" to hold the address of "foo", because that is the purpose of "bar" (i.e., to hold the address of a function), so that the expressions "bar;", or "bar();" or "writeln (Integer (bar));" will each cause function "foo" to be called.
In conclusion, I think this is what GPC should do:
- "bar := tfunc (foo)" = assign to bar the address of foo, but don't
call foo
- "bar := tfunc (foo ())" = call foo (and also assign to bar the
address of foo?) so that "writeln (integer (bar))" should result in a second call to foo - otherwise, what value does bar hold?
I see two clear cases:
bar := tfunc (@foo) { assign to bar the address of foo }
Yes.
and
bar := tfunc (foo ()) { call foo and assign the return value to bar }
My instincts would say "call foo and assign its address to bar" (because I would have thought that "bar;" should also result in a call to "foo"). In Delphi, calling "bar;" or "bar();" does nothing. Surely that must be wrong? However, my instincts and feelings are irrelevant. There is an ambiguity IMHO, and it should be resolved. Delphi's resolution of it corresponds to yours, and that is fine by me (if only for the sake of compatibility with Delphi), even though I still find it strange that calling "bar" after assigning it a value does nothing.
Plain `foo' should either mean `@foo' or `foo ()' or return variable of function `foo' (but here I am interested in values, so the third case is excluded) depending on context. I am slightly oversimpifing here -- IIRC we sometimes reject `@foo' where `foo' is acceptable, but to point is that we have to decide if we want address of foo or we want the return value.
I think we can resolve things on the basis that; plain "foo" = "@foo" { ( FPC ) } and "foo ()" = "call foo" { ( GPC, Delphi ) }
BTW: "@bar := tfunc (@foo);" is treated in exactly the same way by GPC, Delphi, and FPC (BP, of course, doesn't compile it). In this case, we are stating clearly that what we want is an address.
We have a bunch of syntactic contexts: left hand side of an assignment, initializers, casts, function parameters (three sorts of function parameters: value parameters, variable parameters and functional parameters).
Note that beside plain functions ("function constants") we have also function variables, pointers and results of casts so we can form rather large collection of function valued expressions.
IMHO we should use the same rule for assignment, initializers and value parameters. I am tempted to say that we should use the same rule also for variable parameters and functional parameters, but variable parameters have special restrictions and ATM functional parameters do less strict type checking then assignment.
Casts are really nasty case, since in BP casts frequently give different result then assignment (when both are legal). Also, it seems that BP casts are supposed to handle values (except for casts as lvalues). So for example is:
i := integer(foo);
This calls the function, and assigns its return value.
bar := tfunc(pointer(i));
This type-casts a numeric return value. It is not the same as "bar := tfunc(foo);"
or
bar := tfunc(pointer(integer(foo)));
Off the top of my head, I think FPC would treat this as the same as "bar := tfunc(foo);" - i.e., returning an address. GPC would also treat it as the same - but currently calling "foo" and returning its return value.
(In FPC one should use `longint' instead of `integer'.)
What happens when the return type of `foo' is `pointer'? What if return type of `foo' is pointer to `tfunc'?
I am getting a headache! :-)
Best regards, The Chief -------- Prof. Abimbola A. Olowofoyeku (The African Chief) web: http://www.greatchief.plus.com/