Register to post in forums, or Log in to your existing account
 

Play RetroMUD
Post new topic  Reply to topic     Home » Forums » CMUD Beta Forum
JQuilici
Adept


Joined: 21 Sep 2005
Posts: 250
Location: Austin, TX

PostPosted: Thu Oct 11, 2007 10:05 pm   

[2.05] Incorrect variable scoping with @var and @./var - FIXED IN 2.06
 
Ok...I downloaded the beta yesterday to start converting zMUD scripts. This is my first bug report, and I'm a cMUD newbie, so my apologies if this is a known issue or a misunderstanding on my part. (But I didn't get any relevant hits on a forum search, so...)

Variable scoping appears to be broken, or at least not working in the way that I expected it to work from the documentation.

My expectations were as follows:
Code:
var = value
should set 'var' in the current class (if present) or wherever else it finds a 'var' existing (if not present)
Code:
./var = value
should also set 'var' in the current class (creating it, if one is not present, even if one exists elsewhere)
Code:
/var = value
should set 'var' in the root scope (outside all classes), and not touch any other definition.

And gets (@var, @./var, and @/var) should work similarly.

The problem seems to be in the definition of the 'current class'. If the assignments above appear in, say, an alias in Scope1, and that alias is called from Scope2...I expected the 'current class' to be Scope1, where the alias was defined. In particular, ./var should refer to /Scope1/var, NOT to /Scope2/var under those circumstances.

Here is a concrete example that shows the effect. In an empty, offline session, create Scope1 as follows:

Code:
#delclass Scope1
#delclass Scope2
#unvar /scopeVar

#class Scope1
#newvar scopeVar {uninitialized}
#alias setScopeVar1($value) {
   scopeVar = $value
}
#alias setScopeVar2($value) {
   ./scopeVar = $value
}
#alias setScopeVar3($value) {
   /scopeVar = $value
}
#func scopeVarF1 {#return @scopeVar}
#func scopeVarF2 {#return @./scopeVar}
#func scopeVarF3 {#return @/scopeVar}
#alias showScopeVar1 {#say showScopeVar1: @scopeVar}
#alias showScopeVar2 {#say showScopeVar2: @./scopeVar}
#alias showScopeVar3 {#say showScopeVar3: @/scopeVar}
#class 0


Then run the following test (executed in Scope2):

Code:
#class Scope2
#say -- Start --
showScopeVar1
showScopeVar2
showScopeVar3
#say -- Set 1 --
setScopeVar1 set1
showScopeVar1
showScopeVar2
showScopeVar3
#say -- Set 2 --
setScopeVar2 set2
showScopeVar1
showScopeVar2
showScopeVar3
#say -- Set 3 --
setScopeVar3 set3
showScopeVar1
showScopeVar2
showScopeVar3
#say -- Functions --
#say scopeVarF1: @scopeVarF1()
#say scopeVarF2: @scopeVarF2()
#say scopeVarF3: @scopeVarF3()
#say -- Sanity Check --
#say Scope1: @/Scope1/scopeVar
#say Scope2: @/Scope2/scopeVar
#say Top   : @/scopeVar
#say -- END --
#class 0


I get the following output in my main window:

Code:
-- Start --
showScopeVar1: uninitialized
showScopeVar2:
showScopeVar3:
-- Set 1 --
showScopeVar1: set1
showScopeVar2:
showScopeVar3:
-- Set 2 --
showScopeVar1: set1
showScopeVar2: set2
showScopeVar3:
-- Set 3 --
showScopeVar1: set1
showScopeVar2: set2
showScopeVar3: set3
-- Functions --
scopeVarF1: set2
scopeVarF2: set2
scopeVarF3: set3
-- Sanity Check --
Scope1: set1
Scope2: set2
Top : set3
-- END --


Note that setScopeVar3, scopeVarF3, and showScopeVar3 all appear to work as expected - they operate on /scopeVar in all cases. Unfortunately, the others seem broken:
  • setScopeVar1 and showScopeVar1 operate on /Scope1/scopeVar (correct), but the function scopeVarF1() seems to operate on /Scope2/scopeVar (incorrect).
  • setScopeVar2, showScopeVar2, and scopeVarF2() all operate on /Scope2/scopeVar (incorrect).

If you open up the Package Editor, you can also verify that there are THREE copies of scopeVar - including one in Scope2 (which should never have been created).

The practical effect of this bug is that there is no way to write an alias that only operates on variables within its own class, unless you always completely scope the variable reference (e.g. /Scope1/scopeVar), and that seems broken.

(NOTE: I am happy to provide the real-world example where I discovered this, if needed. This artificial example is pared down for clarity).
_________________
Come visit Mozart Mud...and tell an imm that Aerith sent you!

Last edited by JQuilici on Wed Oct 17, 2007 5:04 pm; edited 1 time in total
Reply with quote
JQuilici
Adept


Joined: 21 Sep 2005
Posts: 250
Location: Austin, TX

PostPosted: Thu Oct 11, 2007 10:42 pm   
 
Upon further review, I have located another relevant thread that may shed some light on this topic. It appears that there WAS a change to these very scoping rules in 2.0x. However, I still believe something is broken, since:
  • Variable references should work the same from within functions and aliases (which they do not - see showScopeVar1 and scopeVarF1 above)
  • There SHOULD be a way to refer easily to 'a variable within the class where this alias is defined' other than using a full scope specifier.

Just my $0.02.
_________________
Come visit Mozart Mud...and tell an imm that Aerith sent you!
Reply with quote
Zugg
MASTER


Joined: 25 Sep 2000
Posts: 23379
Location: Colorado, USA

PostPosted: Mon Oct 15, 2007 7:42 pm   
 
This is what I get in v2.06:
Code:
-- Start --
showScopeVar1: uninitialized
showScopeVar2:
showScopeVar3:
-- Set 1 --
showScopeVar1: set1
showScopeVar2:
showScopeVar3:
-- Set 2 --
showScopeVar1: set2
showScopeVar2: set2
showScopeVar3:
-- Set 3 --
showScopeVar1: set2
showScopeVar2: set2
showScopeVar3: set3
-- Functions --
scopeVarF1: set2
scopeVarF2: set2
scopeVarF3: set3
-- Sanity Check --
Scope1: set1
Scope2: set2
Top : set3
-- END --

And it all looks fine to me. Aliases and functions are returning the same results. Aliases and functions execute within the *current* class, *not* the class in which they were defined. You can enabled the "Set as Default when executing" option for your Scope1 class, and then the aliases within will set the current class to Scope1 when they are executing.
Reply with quote
JQuilici
Adept


Joined: 21 Sep 2005
Posts: 250
Location: Austin, TX

PostPosted: Wed Oct 17, 2007 5:02 pm   
 
Confirmed fixed in 2.06, and I understand the explanation of 'Set as Default' (not the behavior I expected, but working as designed).

I am going to have to do some self-education (and probably create some bigger test-cases) to truly understand how namespace scoping rules work in cMUD. More news when I have it, and I may take a swipe at a help page when I get my head straight about the whole thing.
_________________
Come visit Mozart Mud...and tell an imm that Aerith sent you!
Reply with quote
Zugg
MASTER


Joined: 25 Sep 2000
Posts: 23379
Location: Colorado, USA

PostPosted: Wed Oct 17, 2007 5:36 pm   
 
Glad it's working for you now too. Yeah, the scoping rules can be a bit tricky. One of the hard parts about CMUD is trying to do stuff the "right" way (or the expected way) and yet still maintain a high level of compatibility with zMUD. So when you find odd features, such as the "Set as Default", it's usually because of zMUD compatibility issues.
Reply with quote
Display posts from previous:   
Post new topic   Reply to topic     Home » Forums » CMUD Beta Forum All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

© 2009 Zugg Software. Hosted by Wolfpaw.net