|
|
|
|
|
|
| |
| |
|
|
From: William F Pokorny
Subject: A painful lesson regarding function arguments. u=x, v=y.
Date: 27 Sep 2021 09:39:29
Message: <6151c991$1@news.povray.org>
|
|
|
| |
| |
|
|
Though long a user of user functions, today I ran face first into a
parameter naming trap which had me tangled up for hours. Though perhaps
not too surprising in hindsight, thought I'd pass along the lesson learned.
Fn0 = function (x,y,z) {...} // OK. Pass anything you want for x,y,z.
Fn1 = function (v) {...} // OK. Pass anything you want for v.
Fn2 = function (x,y,z,v) // Boom! What you pass for v overwrites y.
Looks to be related to u and v being synonyms for x and y. Something like:
Fn3 = function (x,y,z,_v) {...} // OK. Pass what you want.
Bill P.
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
William F Pokorny <ano### [at] anonymousorg> wrote:
> Though long a user of user functions, today I ran face first into a
> parameter naming trap which had me tangled up for hours. Though perhaps
> not too surprising in hindsight, thought I'd pass along the lesson learned.
>
> Fn0 = function (x,y,z) {...} // OK. Pass anything you want for x,y,z.
>
> Fn1 = function (v) {...} // OK. Pass anything you want for v.
>
> Fn2 = function (x,y,z,v) // Boom! What you pass for v overwrites y.
>
> Looks to be related to u and v being synonyms for x and y. Something like:
>
> Fn3 = function (x,y,z,_v) {...} // OK. Pass what you want.
>
> Bill P.
Interesting! Thanks for the breakdown. I think I ran into a similar problem at
some point in the past year, but didn't try to pursue it (due to sheer lack of
understanding) and moved on.
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
This behaviour is kind-of warned about in the docs:
http://www.povray.org/documentation/3.7.0/r3_3.html#r3_3_1_8_3
....although I must admit I didn't know this before your post, and I only
stumbled on that doc entry because I happened to be doing something with
functions recently too. One to remember!
Bill (the other P)
Post a reply to this message
|
|
| |
| |
|
|
From: William F Pokorny
Subject: Re: A painful lesson regarding function arguments. u=3Dx, v=3Dy.
Date: 29 Sep 2021 18:41:52
Message: <6154ebb0$1@news.povray.org>
|
|
|
| |
| |
|
|
On 9/29/21 5:25 PM, Bill Pragnell wrote:
> This behaviour is kind-of warned about in the docs:
>
> http://www.povray.org/documentation/3.7.0/r3_3.html#r3_3_1_8_3
>
> ....although I must admit I didn't know this before your post, and I only
> stumbled on that doc entry because I happened to be doing something with
> functions recently too. One to remember!
>
> Bill (the other P)
>
Hi Bill :-). Thanks for pointing it out. I'm glad there is some warning
in the documentation. And I note there are two types of argument traps
to remember there - and not just the one into which I fell!
//--- Duplicate arguments are ignored. (povr branch only)
#include "functions.inc"
#declare Fn00 = function (a,b,c,a,b,c) {f_boom(a,b,c,0,0,0)}
#declare Fn01 = Fn00(1,2,3,4,5,6);
#error "Parse test. Stop early."
//---
Generates:
----------
Possible Parse Error:
f_boom
1(x) -> 1,
2(y) -> 2,
3(z) -> 3,
4(0) -> 0,
5(1) -> 0,
6(2) -> 0
Fatal error in parser: Uncategorized error.
//--- u,v synonyms for x,y. Last spec wins. (povr branch only)
#include "functions.inc"
#declare Fn00 = function (x,y,z,u,v,a) { f_boom(x,y,z,u,v,a) }
#declare Fn01 = Fn00(1,2,3,4,5,6);
#error "Parse test. Stop early."
//---
Generates:
----------
Possible Parse Error:
f_boom
1(x) -> 4,
2(y) -> 5,
3(z) -> 3,
4(0) -> 4,
5(1) -> 5,
6(2) -> 6
Fatal error in parser: Uncategorized error.
I think it'd be better to flag these argument issues as a problems
during parsing, but I'm not sure at the moment how to do it.
Bill P.
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
William F Pokorny <ano### [at] anonymousorg> wrote:
> On 9/29/21 5:25 PM, Bill Pragnell wrote:
> > This behaviour is kind-of warned about in the docs:
> >
> > http://www.povray.org/documentation/3.7.0/r3_3.html#r3_3_1_8_3
> >
> > ....although I must admit I didn't know this before your post, and I only
> > stumbled on that doc entry because I happened to be doing something with
> > functions recently too. One to remember!
> >
> > Bill (the other P)
(or: The other Bill P.)
I thought it might be amusing and instructive to write a function that really
mixes up the synonymous argument names, and maybe using ones not invoked in the
function call - have you tried that experiment?
> I think it'd be better to flag these argument issues as a problems
> during parsing, but I'm not sure at the moment how to do it.
>
> Bill P.
When an argument gets tokenized, can you flag it as "set", and then issue a
warning when it gets tokenized again that the previous value is being
overwritten?
PS
I would also like to see some warnings on vector expansion, since missing a
comma often inadvertently sends a 2-component vector to the parser rather than
the intended 3-component one.
<2, -3, 0> might be coded as <2 -3, 0>, leading to <-1, 0> which then gets
expanded.
Post a reply to this message
|
|
| |
| |
|
|
From: William F Pokorny
Subject: Re: A painful lesson regarding function arguments. u=3D3Dx, v=3D3Dy.
Date: 30 Sep 2021 06:33:10
Message: <61559266$1@news.povray.org>
|
|
|
| |
| |
|
|
On 9/29/21 7:32 PM, Bald Eagle wrote:
> I thought it might be amusing and instructive to write a function that really
> mixes up the synonymous argument names, and maybe using ones not invoked in the
> function call - have you tried that experiment?
>
>> I think it'd be better to flag these argument issues as a problems
>> during parsing, but I'm not sure at the moment how to do it.
...
> When an argument gets tokenized, can you flag it as "set", and then issue a
> warning when it gets tokenized again that the previous value is being
> overwritten?
(Maybe - for some situations)
As to your first question (no). I just tried this in the povr branch:
#declare Fn00 = function (x,y,u,z,y,x,z) { f_boom(x,y,z,u,v,0) }
#declare Fn01 = Fn00(1,2,3,4,5,6,7);
getting:
f_boom
1(x) -> 6,
2(y) -> 5,
3(z) -> 7,
4(0) -> 6,
5(1) -> 5,
6(2) -> 0
So...
The last out of order x, sets x and u in the function body.
The last y sets v which is not in the argument list, but where the v is
used in the body of Fn00(AA).
The last z set is used, making the whole x,y,z,u,v set a - last one set
wins collection - where x,u and y,v are aliases for each other.
---
(AA) Which led me to try:
#declare Fn00 = function (a,a,a,a,a,a,a) { f_boom(x,y,z,u,v,a) }
#declare Fn01 = Fn00(1,2,3,4,5,6,7);
which generates:
f_boom
1(x) -> 0,
2(y) -> 0,
3(z) -> 0,
4(0) -> 0,
5(1) -> 0,
6(2) -> 1
which highlights another kind of trap! Namely, using z,y,z,u or v
internal to a function body where you've not specified them in the
argument list. Looks like those all default to 0 and the variables are
available within the function body without complaint from the parser
whether they are getting set by some explicit (or defaulted) argument
passing or not. The 'not' case being the exposure.
With this:
#declare Fn00 = function (a) { f_boom(x,y,z,u,v,a) }
#declare Fn01 = Fn00(1);
The 'a' ends up set to 1 in the body and again all of x,y,z,u,v are
available in the body and set to 0.
Yep, some parse time checks would be good. This all has me wondering how
often I've fallen into one of these traps over the years and not known
it. The episodes where I get frustrated and toss a whole set of
functions in the trash bin and start completely anew - because I cannot
'see' the issue with what I'd coded.
Aside: The argument duplicate defaulting for macros isn't the first set
as is happening with 'a' above, but last one set. With the function
arguments I believe by the time the parsing sees the second 'a' it
understand it to be a value - there is already an entry in the local
symbol hash table for 'a'. So, for any after the first, it substitutes
the value it knows 'a' to be.
>
> PS
>
> I would also like to see some warnings on vector expansion, since missing a
> comma often inadvertently sends a 2-component vector to the parser rather than
> the intended 3-component one.
> <2, -3, 0> might be coded as <2 -3, 0>, leading to <-1, 0> which then gets
> expanded.
>
Yes, that one has gotten me a few times too.
Thinking aloud, with this kind of stuff, might well be a stand alone SDL
linter utility would be easier to implement. Static code analysis for
SDL! :-o
Bill P.
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
William F Pokorny <ano### [at] anonymousorg> wrote:
> which highlights another kind of trap! Namely, using z,y,z,u or v
> internal to a function body where you've not specified them in the
> argument list. Looks like those all default to 0 and the variables are
> available within the function body without complaint from the parser
> whether they are getting set by some explicit (or defaulted) argument
> passing or not. The 'not' case being the exposure.
I vaguely recall running into this (or very similar) in the past year or so, and
think I commented on it. Still good to keep it closer to the front burner for
general awareness.
> With the function
> arguments I believe by the time the parsing sees the second 'a' it
> understand it to be a value - there is already an entry in the local
> symbol hash table for 'a'. So, for any after the first, it substitutes
> the value it knows 'a' to be.
Ooooh. Tricky. I wouldn't have anticipated that.
> Thinking aloud, with this kind of stuff, might well be a stand alone SDL
> linter utility would be easier to implement. Static code analysis for
> SDL! :-o
Yes, I think that sort of general idea has been poked with a stick a few times.
I've even thought of unrolling all of the code and spreadsheeting out all of the
"live" values. All of which is way beyond my present coding skills in any
language.
Very cool experiments. Somewhat hard to follow, and I'm sure there are a few
more things that could be tried. I'm assuming that using "a" (or any other
non-special variable name) in a function without declaring it in the argument
list gives the expected error.
Maybe writing a script using parse_string to cycle through a list of variable
names might highlight some things we haven't even thought of yet.
I'm guessing keywords are obviously forbidden in macro and function argument
lists and equation expressions (just asking because x, y, z, u, v, t) are all
"keywords" - but transmit, filter, red, green, blue, r, g, b, are all
dot-notation variable-extensions....
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
William F Pokorny <ano### [at] anonymousorg> wrote:
>
> which highlights another kind of trap! Namely, using z,y,z,u or v
> internal to a function body where you've not specified them in the
> argument list. Looks like those all default to 0 and the variables are
> available within the function body without complaint from the parser
> whether they are getting set by some explicit (or defaulted) argument
> passing or not. The 'not' case being the exposure.
I just discovered this last night. See Mysterious function argument in
p.documentation.inbuilt.
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
|
|