From: William F Pokorny
Subject: Bug and detail for, new at v3.8, global and local dictionaries
Date: 20 Oct 2023 14:49:53
If using the local and global, parsing automatic, dictionaries, it's
safe to use local dictionary test inside macros. This capability is
essential to the macro, optional parameter defaulting also new to v3.8.
#macro Foo(P1, optional P2)
#ifndef(local.P2) #local P2 = 0; #end // provide default for P2
Otherwise, be very careful as there is at least one bug and also some
complicated behavior - which might or might not be the best thing to
do... Basically, other documented behavior may or may not work!
Recently, I again wondered, how the, new at v3.8 and later, 'global' and
'local' dictionaries of identifiers worked at the very top level. The
#local identifiers are effectively globals when used at the very top of
the scene hierarchy.
Well, in the top file, #local identifiers are added to both the parser's
automatic local and global dictionaries of identifiers. Also true for
all #declare identifiers, declares from the command line, #for loops
iteration variables (treated internally as non-scoped #local(s)) and
such in the top file.
The implication here, if leaning on the local / global dictionaries to
decide things in your scene, is that the conditional test results will
change as you move code about in the hierarchy of files. Some of this we
might expect, while other behavior very likely not.
I went on to do a bunch of test cases on and off over a the past couple
days and that testing turned up relatively basic bug.
If we have three files in A.pov, B.inc, and C.inc where the include
A.pov -> B.inc -> C.inc
where we have #local identifiers defined in B.inc, these are not getting
added to the global (or local for that matter) dictionary while reading
/ including C.inc. This a bug.
Those B.inc scoped variables are effectively global for the code in
C.inc. A #declare in C.inc for #local identifier names in B.inc will
update those identifiers in the B.inc scope - ones 'effectively global'
while in C.inc. The #ifdef(), #ifndef() and defined() all return the
appropriate results for the #local identifiers in B.inc. Namely, those
older features see the the #local names in B.inc as defined while in
C.inc. I've attached a failing test case tarball set up with A.pov ->
B.inc -> C.inc.
Aside: I suspect this bug might have gotten passed us due the top level
seeing all the methods of setting up identifiers as creating global ones
(and local). If we imagine the testing was done with something more
like: A.pov -> B.inc alone. Well, things work then because of that
global/local duality in the very top file.
Not sure when I'll get around to looking at the bug. My current leaning
for the global/local duality at the top is everything should be in the
global dictionary and not the local one too, but, I should let that
thought bang around in my head for a while.
Post a reply to this message
Download 'local_global_dictbug.tar.gz' (2 KB)
William F Pokorny <ano### [at] anonymousorg> wrote:
> The implication here, if leaning on the local / global dictionaries to
> decide things in your scene, is that the conditional test results will
> change as you move code about in the hierarchy of files. Some of this we
> might expect, while other behavior very likely not.
It looks like you may be finally touching on the elusive bug that has plagued me
in a number of "recent" projects - where I was having problems with certain
macro results not being defined, especially (it seemed) when I was running those
macros from within include files.
I'm not sure if I posted full code for those examples or not, and it's a bit
worrisome, since it suggests that more such things may be lurking in the parser
- and even more worrisome - that there may be some fundamentally flawed
logic/implementation in the way the entire parser is structured (aside from the
obvious things that we've discussed over the past decade(s) ;) )
I can't recall all of the various instances where I've run into these problems,
but certainly it was a recurring theme in the kumiko triangles project:
I've experimented with tracking the nesting level of the SDL code in the past,
and maybe there's a way to make that visible to the SDL from within source
without slowing things down / adding too much overhead.
Also, I'm wondering if in your povr branch, you could try addressing the highly
ambiguous "#end" directive and switching over to #endif #endfor etc.
Since you're coding source (in C? c++?), it would be interesting to hear your
"ramblings" on the types of data structures and code-flow directives we're
currently missing in SDL that you think would be of use.
Great work tracking down these parse errors. They can seriously challenge
one's sanity when trying to debug scenes in SDL.
Post a reply to this message
From: William F Pokorny
Subject: Re: Bug and detail for, new at v3.8, global and local dictionaries
Date: 22 Oct 2023 13:08:20
On 10/22/23 10:36, Bald Eagle wrote:
> I've experimented with tracking the nesting level of the SDL code in the
> past, and maybe there's a way to make that visible to the SDL from
> within source without slowing things down / adding too much overhead.
Unsure in total, what sort of tracking you mean, but...
I did take a run in povr at a debug option for the include files and it
is still available via the environment variable:
POV_PARSER_File_Text_INC_DEBUG, but with scenes making use of the
parse_string / Parse_String macro for dynamic SDL code it's unusable as
one drowns in debug output so it isn't today a run time povr option.
It's on my list to create a parse_string feature which doesn't use the
include file mechanism, but some sort of 'memory file' instead.
> Also, I'm wondering if in your povr branch, you could try addressing the
> highly ambiguous "#end" directive and switching over to #endif #endfor
Yeah, I find myself typing #endif all the time when coding SDL! It's not
all that easy to implement differing 'end tokens' unfortunately; So,
it's not a near term povr work item.
> Since you're coding source (in C? c++?), it would be interesting to
> hear your "ramblings" on the types of data structures and code-flow
> directives we're currently missing in SDL that you think would be of
:-) Expect the list here goes on for a while and general 'list' (c++
vector) support one feature I'd like(*). I'll leave further rambling on
this topic for another day.
(*) Some work has been done in this direction by jr and others with
> Great work tracking down these parse errors. They can seriously
> challenge one's sanity when trying to debug scenes in SDL.
Thanks & agree (my sanity is questionable as is).
Took a quick look at your reference to the kumiko triangles project and
I realize I didn't test 'deprecated' or the 'global', 'local' pseudo
dictionaries with tuple assignments. The combinations go on and on...
With the pseudo dictionaries my current recommendation would be to use
only in #macro 'local.' ones.
On writing that, I had the thought we can, I think, implement a
trustworthy 'global.' test, at least, inside macros with something like:
#if ((!defined(local.V123)) & (defined(V123)))
Pending fixes / changes, I'd say stay away 'global' altogether and use
'local' only within macros for conditional tests or references. Further,
don't do any assignment / redefinition / undef of identifiers via the
'global' and 'local' dictionaries.
In povr, wondering if I can make 'global' pseudo dictionary use a parse
error for now... I worry about where I have myself used it. I know it's
there in povr's shipped munctions.inc and setidtypes.inc includes.
Probably none of my 'global' use is absolutely necessary in those though.
What if, we change the expected and documented behavior from:
"Included are the two pseudo-dictionaries local and global they
represent the most local and the least local or global identifiers
"Included are the two pseudo-dictionaries local and global, they
represent the most local and the scene's top file's identifiers
The latter is closer to what we have today by implementation. Then we'd
probably need a new way(s) to create / modify / undef identifiers which
strictly works with the top file's identifiers. A #top V123 = 123; which
would bypass any identifier name masking.
The 'least local' which are not today (always?) in the global dictionary
could be isolated with the code posted above or
#if ((!defined(global.V123)) & (!defined(local.V123)) & (defined(V123)))
depending on needs.
Hmm. Is that enough to handle aimed modifications. Maybe, yes, except
where the #local masking is more than one instance deep(a), but we
probably don't much need to whack the intermediate locals. They go away
when we exit the macro or file context, so undef useless there really -
and redefinition too seems unlikely excepting maybe as a way to 'return
values' from a included file's context(a).
(a) - There is sort of a "most global, not top level" class of
identifiers possible too I guess.
I don't know. Thinking aloud...
Might be simpler to fix the bug / match what is documented for behavior,
but it leaves the pseudo dictionaries as less of a solution to
identifier name masking than perhaps they could be.
Post a reply to this message