For Yorick parser (I use the CVS version of 2010-11-15), a keyword is by default an extern variable. This is demonstrated by the following piece of code which show that extern variable "key" is set by function f2:

The problem mentioned above is not the behavior that is documented in Yorick documentation and since it may have unwanted side effects, I think that the parser should be fixed.

The other possibility is to change the doc. but this behavior can hardly be seen as a feature. The scoping rules of Yorick (p. 11-12 of the manual) are simple but already somewhat perturbating for new users. If keywords are also external variables by default it would be very difficult even for a Yorick master to avoid conflicts.

I have tested an "old" (2.1.04) Yorick version and the problem is the same.

Sorry for insisting on this issue but it occured again to me, and I shooted in my foot .

In Yorick, the first time a symbol appears in the code flow of a function, it is considered as an external one unless it appears as the symbol defined by a simple assignation (as in: var = expr;) or unless it is a dereferenced member (as in: obj.memb; or ptr->memb;).

This means that in every line below, symbol foo is external by default while bar is not (db is a structure or any object which implements member dereferencing, ptr is a pointer on a such object, obj is an OXY object):

Except for the three first examples (the function call and member dereferencing), this behaviour is not really intuitive. I guess from this observed behavior that the parser is able to recognize member dereferencing, hence it should be possible to solve the issue for and fourth case (keyword). Due to dynamic typing, the parser cannot be fixed to solve for the last case (OXY dereferencing or method calling).

I had not realized this misfeature. The above analysis is incorrect, however -- this is an exceedingly subtle point. There are actually THREE possible states for a literal name in a yorick function: It may be local, it may be extern, or it may be undecided. The correct behavior for a keyword argument when the keyword name has never been mentioned SHOULD be that it remains undecided. This is because the keyword name belongs to the namespace of the function being called, not to the namespace of the caller. For example, the name of a member after the . or -> operators does not belong to the namespace of the function, but to the namespace of the struct or object -- therefore using a member name in a function leaves the name undecided, that is, you are still free to declare it either local or extern. Both these are legal:

Code:

func f { g.name; extern name; }func f { g.name; local name; }

Compare this to:

Code:

func f { g,name=7; extern name; }func f { g,name=7; local name; }

The second of these has always been a syntax error, because the use of name as a keyword (thus belonging to the namespace of g) incorrectly forces name to be an extern if it has not already been declared. In other words, using a name as a keyword incorrectly constitutes a first reference in a caller if that name has never been used.

Unfortunately, the parser is written so that it would be very difficult to do the correct thing, and leave the keyword name undecided, so that neither of the sample f functions is a syntax error. I agree with Eric to the extent that if I must have incorrect behavior, it would be better to err in the opposite direction and make the (incorrect) choice that the first reference of a name as a keyword produces a local. Therefore, I have committed a change to the parser which produces the opposite behavior henceforward.

I'll probably regret this change, as it may well break code that had previously worked. As in all cases where yorick's informality causes problems, this one could have been avoided (and still can be avoided) by putting an explicit local or extern declaration before the use of a symbol as a keyword.

Be warned that if I ever get around to rewriting the parser, this behavior will change once again, so that using a name as a keyword leaves its status as a variable undecided, just as using it as a member name (for either the . or -> operator) currently, and correctly, leaves its status undecided. In the meantime, if you want really bulletproof code and you refuse to use explicit extern and local declarations, you should avoid using keyword names to implicitly declare variable scope, by altering the names of any of your own variables so they do not conflict with keyword names in functions you call.

Eric's analysis of the problem with the oxy syntax is absolutely correct -- the use of obj(foo) unexpectedly causes foo to take on extern scope if you use it elsewhere in your function. This is (another) misfeature of the object semantics I invented. You need to either explicitly or implicitly declare foo before this use, or better yet, avoid using foo as a local variable name whenever possible.

Wed Dec 22, 2010 2:07 pm

Thierry Michel

Yorick Guru

Joined: Sat Jan 22, 2005 2:44 pmPosts: 86Location: Pasadena, CA

"hcp" undifined in graph.i - hcps
Is this an example of the side effect you mentioned?
fix:

It is indeed. I fixed this in CVS, but I really hope it isn't too common. I'm regretting the change already, since the code that produces either misbehavior looks right -- it almost certainly would have been better to stick with the original choice... I'll leave it as is for now, and hope that there aren't more examples like this lying in wait...

This issue is finally correctly resolved. If the first reference to a symbol in a function is as a keyword, yorick no longer forces the symbol to have either local or extern scope in the function. This prevents either common use case from giving unanticipated results. See https://github.com/dhmunro/yorick/commi ... 352d3402fd for details.

Who is online

Users browsing this forum: No registered users and 1 guest

You cannot post new topics in this forumYou cannot reply to topics in this forumYou cannot edit your posts in this forumYou cannot delete your posts in this forumYou cannot post attachments in this forum