Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

State changes in global functions

Jon Marlin
Builder, Coder, RL & SL
Join date: 10 Mar 2005
Posts: 297
03-21-2005 06:44
Last night I was in-world, working on my new vehicle script. I'm actually using the FSM capabilities in LSL, and I also like to make the event handlers in each state call a function to handle the event. This makes the whole thing much simpler to read and understand, in my opinion.

So, for instance, I have the following state:

idleState {

changed (integer change) {
handleRunningChangedEvent (change);}

control (key id, integer level, integer edge) {
handleIdleControlInput (id, level, edge);}
}

In the handleIdleControlInput function, I want to (under certain conditions) change the state. Sometimes this seems to work, but once last night I got a compiler error that you are not allowed to change the state from within a global function.

Is there a rule about this?

- Jon
Jeffrey Gomez
Cubed™
Join date: 11 Jun 2004
Posts: 3,522
03-21-2005 07:38
It seems you want idleState to be a state. It needs to be denoted state idleState.

You can change state only from within the braces of another state. If you're outside of those braces... say, in a function this_is_a_test(integer param) {}, the compiler will get mad at you if you try to change states.

In other words, do like the compiler says - don't change states in a global function. It read your idleState as a function.

Got state?
_____________________
---
Jon Marlin
Builder, Coder, RL & SL
Join date: 10 Mar 2005
Posts: 297
03-21-2005 07:54
From: Jeffrey Gomez
It seems you want idleState to be a state. It needs to be denoted state idleState.

...

In other words, do like the compiler says - don't change states in a global function. It read your idleState as a function.

Got state?


Sorry, yes, I fixed the part where needed to declare idleState to be a state -- I just can't get into SL from work to get the updated script, so I was posting from my old copy on my computer.

The funny this is, the compiler is not at all consistent about this -- there are a number of places where I was changing the state from within a global function called from an event handler of a state. The compiler complained about one of those, and I changed that one, but it didn't complain about the others, and they even seem to work sometimes.

I view this as a major disappointment -- I can't share common code between states where that code might also do a state change.

- Jon
Jeffrey Gomez
Cubed™
Join date: 11 Jun 2004
Posts: 3,522
03-21-2005 08:00
From: Jon Marlin
I view this as a major disappointment -- I can't share common code between states where that code might also do a state change.

- Jon

Not locally, no - but isn't this what global variables are for?

As for state changes as per a function, yeah - but considering you're usually returning to an event of some sort, it's typically a small loss.
_____________________
---
Jon Marlin
Builder, Coder, RL & SL
Join date: 10 Mar 2005
Posts: 297
03-21-2005 08:25
From: Jeffrey Gomez
Not locally, no - but isn't this what global variables are for?

As for state changes as per a function, yeah - but considering you're usually returning to an event of some sort, it's typically a small loss.


Well, when I say "state" in this context I'm referring to the current state of the FSM, not state held in a global varianle.

Its a small loss unless you change to more than one state depending on condition factors being tested in the event handler function. Then you need a way to propagate the state change decision back to the calling event handler, and put in a big conditional that does the right thing there. Might as well not use the states at all if I have to do that.

I guess I'm just going to have to live with having big ugly chunks of code in the event handler contexts of the state definitions.

- Jon
Malachi Petunia
Gentle Miscreant
Join date: 21 Sep 2003
Posts: 3,414
03-21-2005 09:17
Or you could do something like:
CODE
integer someGlobalFunction() {
if(...)
return TRUE;
else
return FALSE;
}

default {
touch_start(...) {
if(someGlobalFunction())
state otherState;
}
}

state otherState {
...
}
There has been theorhetical debate as whether LSL states are like FSM (or DFA) states. I don't think there has been a concensus on the matter. I read LSL "state" as "unique set of event handlers", but that's me.
_____________________
Ushuaia Omega
Registered User
Join date: 14 Mar 2005
Posts: 5
03-21-2005 09:49
http://secondlife.com/badgeo/wakka.php?wakka=FunctionStateChangeHack

You can change state within a global function if the state change statement is within a conditional statment that always evaluates to TRUE.

This is considered to be a hack and there can be adverse effects associated with doing this.
Lex Neva
wears dorky glasses
Join date: 27 Nov 2004
Posts: 1,361
03-22-2005 11:47
I'm convinced this is a hack, a bug in the compiler that should never, ever be used. From the comments in "Hacks" in the wiki (http://secondlife.com/badgeo/wakka.php?wakka=Hacks&show_comments=1#comments):

From: someone

the "consequences" link in the "Change state within a function" section is broken since the forum change. What are the consequences of this piece of code?
-- NeoRebus (2004-07-05 15:44:40)

It fucks up the stack. You should never use it. It's a bug and it will hopefully be fixed soon.
-- EzharFairlight (2004-07-05 17:50:17)

You just have to be very careful about using it. It basicly clears the stack out completely, from any depth within the stack (it doesnt even finish the current running event). That might cause some internal problems (memory leaks?), but I didnt see any with my tests on it. You can blame the dead link on LL, who recently fucked up the forums. Dont use the state-change hack on functions that are supposed to return a value, since when you are trying to return a string or list, and change state within the function, the VM throws a Runtime Bounds Error.
-- ChristopherOmega (2004-07-05 18:36:07)

It seems that the three above comments are now outdated, Ive created a new page with updated information on the state change function hack here: FunctionStateChangeHack
-- ChristopherOmega (2005-02-21 22:14:43)


Even though Christopher has retracted his negative comments an written a page all about how to do state changes within a function (the one Ushuaia linked to), it's still pretty clear that changing state within a funciton is very dangerous. The compiler tries its best to tell you not to do this, and I'm sure there's a reason. It only happens that there's a bug that the compiler's protection fails to prevent you from shooting yourself in the foot if you sufficiently disguise what you're doing from it.

I get very nervous about that "fucks up the stack" comment. That says to me that even if it happens to work now, that's probably only a fluke. You may well notice very weird errors, like having an event in the new state returning into the old state or something bizarre like that. You might leak stack frames, slowly eating away at your memory. Don't do this!

I know it makes your scripting difficult, and I hope they make this possible and supported very soon, but right now, I think it's a very quick way to shoot yourself in the foot.

By the way, I recently had need to dynamically change states. I wished I could set a string variable to the name of a state and switch to whatever state was named in that variable. My workaround was to make a global string variable, "next_state", and then a state something like this:

CODE

state state_change {
state_entry() {
if (next_state == "somestate1")
state somestate1;
else if (next_state == "somestate2")
state somestate2;
else if (next_state == "somestate3")
state somestate3;
}
}


I just change states to the "state_change" state, which immediately changes states to the one I actually want to be in.

You could make use of this by setting the next_state variable to the empty string before calling your function, and then check to see if it's non-empty after the function returns, and if so, switch to the state_change state.
Christopher Omega
Oxymoron
Join date: 28 Mar 2003
Posts: 1,828
03-22-2005 12:12
We really need Linden input on this. Giving functions the ability to change state proves useful in many valid scenerios. At the moment, I have no reservations concerning the usage of the aformentioned hack, save that one day LL will spontaniously decide to remove (or break) it, like the change to how long listen handles stayed around.

Right now, state change acts like a "return;" statement. In functions with no return values (events included), this is completely valid. I propose two solutions:

1. Have the compiler halt compilation when it sees a state change in a function that returns a value, otherwise enable state changes in functions without return values.

2. Make the state directive, instead of returning, set a flag that indicates to the virtual machine, that when the event is finished executing completely, then change state to where the flag indicates.

The second would be a better solution IMO, as it would get rid of several precedance oddities that occur when multiple state changes are triggered in series (see the FunctionStateChangeHack page) and it would make script execution more predictable and regular.
==Chris
_____________________
October 3rd is the Day Against DRM (Digital Restrictions Management), learn more at http://www.defectivebydesign.org/what_is_drm
Malachi Petunia
Gentle Miscreant
Join date: 21 Sep 2003
Posts: 3,414
03-22-2005 14:17
From: someone
...By the way, I recently had need to dynamically change states. I wished I could set a string variable to the name of a state and switch to whatever state was named in that variable. ...
I think this would be a non-issue if they'd just implement the Comefrom statement. Computed comefroms are even more flexible.
_____________________