|
|
|
|
|
|
| |
| |
|
|
From: Florian Brucker
Subject: Scope of identifiers in nested Macros
Date: 1 Jan 2004 15:08:46
Message: <3ff47e4e@news.povray.org>
|
|
|
| |
| |
|
|
When rendering the following code:
<POV>
#macro M1(Param)
#local Param = Param - 1;
#debug concat("Param = ",str(Param,0,0),"\n")
#end
#macro M2(Param)
#local a = 0;
#while (a<10)
M1(Param)
#local a = a + 1;
#end
#end
M2(100)
</POV>
I would expect the line "Param = 99" being printed 10 times. Instead,
the output is
<Output>
Param = 99
Param = 98
Param = 97
Param = 96
Param = 95
Param = 94
Param = 93
Param = 92
Param = 91
Param = 90
</Output>
I think this does not match the behaviour described in the documentation
in section "6.2.2.3 Identifier Name Collisions".
Any Comments?
Happy new year everybody
Florian
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
Florian Brucker <tor### [at] torfboldcom> wrote:
> M1(Param)
I didn't test, but doing "M1((Param))" should do what you expect.
The behaviour of the parser is interesting with regard to #local and
macro parameters. AFAIK if you give an identifier directly as a macro
parameter, any #local inside that macro will modify the original
identifier. If you give a *value* (instead if an identifier) as parameter,
the macro will get a copy of that value and will only modify this temporary
copy.
Putting the identifier into parentheses will make it an expression
which resulting value will be given as parameter instead of the identifier
itself. That is, the difference between "Param" and "(Param)" is that
the first is an identifier (which is then modified in the macro) while
the second is a float expression (which result is the value of Param),
which value is temporarily copied to the macro.
The difference is similar to doing "void foo(int& i)" or "void foo(int i)"
in C++, but the syntactical difference is more subtle (because you decide
whether the parameter is passed by reference or by value at the calling
place instead of the macro definition).
If you want to be sure that your macro will not modify an identifier
given as parameter, you should make an explicit copy of it inside your
macro.
I think this should be explained in the documentation if it's not already.
--
#macro N(D)#if(D>99)cylinder{M()#local D=div(D,104);M().5,2pigment{rgb M()}}
N(D)#end#end#macro M()<mod(D,13)-6mod(div(D,13)8)-3,10>#end blob{
N(11117333955)N(4254934330)N(3900569407)N(7382340)N(3358)N(970)}// - Warp -
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
> I think this should be explained in the documentation if it's not already.
IMHO an implementation like the documentation is described would be
better that updating the documentation. I think the current behaviour is
not at all intuitive and can create errors which are very hard to spot.
Although I have to admit that I have never encountered this error before :)
BTW, any chance the POV-Syntax will be extended with a include-file-wide
identifier scope? Something like (In an include file):
#public SomeValue = 10; //Global scope, visible to all files & macros
#private AnotherOne = 1; //Include-File scope, only visible to the
//Include file and macros within the file
#local LastButNotLeast = 5; //Macro scope, visible only to the macro it
//is declared in
This way one would not have to carry along prefixes in include files to
prevent global scope identifiers from being overwritten.
Florian
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
Florian Brucker <tor### [at] torfboldcom> wrote:
> IMHO an implementation like the documentation is described would be
> better that updating the documentation. I think the current behaviour is
> not at all intuitive and can create errors which are very hard to spot.
But the current behaviour can be useful sometimes.
> BTW, any chance the POV-Syntax will be extended with a include-file-wide
> identifier scope? Something like (In an include file):
If you make a #local in an include file, its scope will be only inside
that file.
--
#macro M(A,N,D,L)plane{-z,-9pigment{mandel L*9translate N color_map{[0rgb x]
[1rgb 9]}scale<D,D*3D>*1e3}rotate y*A*8}#end M(-3<1.206434.28623>70,7)M(
-1<.7438.1795>1,20)M(1<.77595.13699>30,20)M(3<.75923.07145>80,99)// - Warp -
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
> But the current behaviour can be useful sometimes.
Do you mind to give an example?
> If you make a #local in an include file, its scope will be only inside
> that file.
But you can't use it properly in macros:
<test.inc>
#local ID = 2;
#macro Test()
#debug str(ID,0,0)
#end
</test.inc>
<main.pov>
#include "test.inc"
Test()
</main.pov>
Render main.pov and see :)
Florian
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
In article <3ff489d3$1@news.povray.org>,
Florian Brucker <tor### [at] torfboldcom> wrote:
> > I think this should be explained in the documentation if it's not already.
> IMHO an implementation like the documentation is described would be
> better that updating the documentation. I think the current behaviour is
> not at all intuitive and can create errors which are very hard to spot.
> Although I have to admit that I have never encountered this error before :)
It is also very useful. Look at the Isect() and Extents() macros in
shapes.inc, which use this feature to return multiple values.
Things could be clarified quite a bit, though. This is what I would do:
#declare always declares a global variable. Actually, deprecate #declare
and use #global instead. #local always declares a local variable.
If either #declare or #local are used with an existing variable, a
warning is emitted. Existing variables are modified with a #set or #
directive, which require an existing variable:
#local J = 0;
#while(J < 10)
#set J = J + 1;
or
#J = J + 1;
#end
#macro Foo(Param)
#local Param = Param + 1;
#end
Would produce a warning and replace the parameter Param with the local
version, leaving the original unaffected.
#macro Foo(Param)
#declare Param = Param + 1;
#end
Would only produce a warning if a global variable named Param already
existed. It would create that global variable and leave the parameter
unaffected.
#macro Foo(Param)
#set Param = Param + 1;
#end
Would modify the parameter itself.
This also avoids odd typo errors. This code would loop infinitely:
#local I = 0;
#while(I < 10)
#local l = I + 1;
#end
This version would give an immediate error:
#local I = 0;
#while(I < 10)
#set l = I + 1;
#end
The #set keyword is part of the MegaPOV patch collection, but the rest
of it would break backwards compatibility too much to be included.
Unless a new keyword were used for declaring local variables...hmm. How
does this sound?
#declare, #local: obsolete, deprecated, but unchanged in operation for
backwards compatibility.
#global, #def or #define, #set: as described above, with #def declaring
a local variable.
Well, I just wanted to say that the pass by reference is actually a
useful feature...guess I got carried away.
> BTW, any chance the POV-Syntax will be extended with a include-file-wide
> identifier scope? Something like (In an include file):
This already exists: variables defined as #local outside a macro are
local to the include file.
--
Christopher James Huff <cja### [at] earthlinknet>
http://home.earthlink.net/~cjameshuff/
POV-Ray TAG: <chr### [at] tagpovrayorg>
http://tag.povray.org/
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
Christopher James Huff <cja### [at] earthlinknet> wrote:
> #declare, #local: obsolete, deprecated, but unchanged in operation for
> backwards compatibility.
> #global, #def or #define, #set: as described above, with #def declaring
> a local variable.
How would #def be different from #local?
What's wrong with #local? It's certainly a whole lot more descriptive
than #def.
I think that a lot of the confusion-causing problems in the current
macro syntax would be avoided if you could specify if the macro takes
its parameter by value (which would be the default in the current syntax)
or by reference (with a special symbol or keyword).
If the macro says that the parameter is taken by value then POV-Ray
will always make a temporary copy of the parameter. If it says that it
is taken by reference then it would work as it works currently (that is,
if an identifier was given (and not an expression), then any assignment
will be made to the original identifier).
Example (the & syntax is just a proposition inspired by C++, not
to be taken too seriously):
#macro Foo(Param1, &Param2)
#set Param1 += 1; // Yes, I want these operators as well :)
#set Param2 += 2;
do_something_with_the_params
#end
#local A = 5;
#local B = 5;
Foo(A, B)
// At this point A will be 5, but B will be 7
--
plane{-x+y,-1pigment{bozo color_map{[0rgb x][1rgb x+y]}turbulence 1}}
sphere{0,2pigment{rgbt 1}interior{media{emission 1density{spherical
density_map{[0rgb 0][.5rgb<1,.5>][1rgb 1]}turbulence.9}}}scale
<1,1,3>hollow}text{ttf"timrom""Warp".1,0translate<-1,-.1,2>}// - Warp -
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
In article <cja### [at] netplexaussieorg> ,
Christopher James Huff <cja### [at] earthlinknet> wrote:
> #J = J + 1;
I like this syntax for manipulating already declared variables. It would be
easy to add to the parser (tokenize.cpp) as well...
Thorsten
____________________________________________________
Thorsten Froehlich, Duisburg, Germany
e-mail: tho### [at] trfde
Visit POV-Ray on the web: http://mac.povray.org
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
in news:3ff6ac42$1@news.povray.org Thorsten Froehlich wrote:
>> #J = J + 1;
>
> I like this syntax for manipulating already declared variables.
Why not throw the # away completely?
J = 0;
J = J + 1;
Everything is local, unless it is declared global,
#global J = "global"
Ingo
Post a reply to this message
|
|
| |
| |
|
|
From: Florian Brucker
Subject: Re: Scope of identifiers in nested Macros
Date: 3 Jan 2004 08:23:50
Message: <3ff6c266@news.povray.org>
|
|
|
| |
| |
|
|
>>BTW, any chance the POV-Syntax will be extended with a include-file-wide
>>identifier scope? Something like (In an include file):
>
> This already exists: variables defined as #local outside a macro are
> local to the include file.
See my answer to Warp for what I mean.
Florian
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |