pawn-lang / compiler

Pawn compiler for SA-MP with bug fixes and new features - runs on Windows, Linux, macOS
Other
305 stars 72 forks source link

Fall-back state specifiers are not permitted for state variables. #406

Open On3d4y opened 5 years ago

On3d4y commented 5 years ago

Issue description:

In pawn-lang.pdf:

As a special syntax, when there are no names between the angle brackets, the function is linked to all states that are not attributed to other implementations of the function. The function that handles “all states not handled elsewhere” is the so-called fall-back function.

A state variable is a global variable with a state classifier appended at the end. The scope and the lifespan of the variable are restricted to the states that are listed in the classifier.

Fall-back state specifiers are not permitted for state variables.

Minimal complete verifiable example (MCVE):

#include <a_samp>

new var1 <my_state:state_a>;
new var2 <my_state:state_b>;

// error 085: no states are defined for symbol "var3"
new var3 <>;

// error 017: undefined symbol "var3"; did you mean "var1"?
// warning 203: symbol is never used: "var3"
new var3 <my_state>;

// error 001: expected token: "-identifier-", but found ">"
new var3 <my_state:>;

main() {
    state my_state:state_a;
    Func();
    state my_state:state_b;
    Func();
    state my_state:state_c;
    Func();
}

Func() <my_state:state_a> {
    printf("%d", var1);
}

Func() <my_state:state_b> {
    printf("%d", var2);
}

Func() <my_state:state_c, my_state:state_d> {
    printf("%d", var3);
}

Why not one var3 can work?

Workspace Information:

Y-Less commented 5 years ago

I'd say this is more of a feature request than a bug report @Southclaws. Since apparently pawn-lang.pdf says this shouldn't be allowed, the fact that it isn't is correct. Actually, as a feature request it might be nice to go one further:

Func() <my_state: state_a> // Function in state `state_a` of automata `my_state`.
{
}

Func() <> // Fallback function.
{
}

That code is fine - you have a fallback function, and the automata for the function (since it can only have one) is well defined by another instance.

Func() <my_state: state_a> // Function in state `state_a` of automata `my_state`.
{
}

Func() <my_state> // Function in state `my_state` of the default automata.
{
}

That code is an error, since the compiler thinks you are putting Func in two different automata. The syntax proposed in the original post is also an error:

Func() <my_state: state_a> // Function in state `state_a` of automata `my_state`.
{
}

Func() <my_state:> // Fallback function explicitly in automata `my_state`.
{
}

Normally this is not an issue, since you tend to have multiple copies of a function when using states. A stateful function with only one state is pointless - that's just a normal function. But it does happen, especially with libraries and hooks. I do this with one version of ALS:

OnWhatever() <_ALS: dummy> { return 1; }
OnWhatever() <> { return 1; }

Then if there is a hook, the hook is called in state _ALS: exists; if there is no hook the fallback is called. The dummy function exists purely to set the automata. You can specify multiple states:

OnWhatever() <_ALS: dummy, _ALS: other> { return 1; }

But there's no way to specify multiple states including the fallback explicitly:

OnWhatever() <_ALS: dummy, > { return 1; }

Which wouldn't be needed either if there was a way to specify the automata explicitly as above:

OnWhatever() <_ALS: > { return 1; }

Furthermore, if ONLY a fallback function exists (explicit or otherwise) the whole state stub can be simply omitted and the function treat as a normal function. In that case, the explicit automata specification becomes unnecessary and the error should be removed:

OnWhatever() <> { return 1; }

That would be called in all cases (thus not needing the internal switch), and if a hook did exist as:

OnWhatever() <_ALS: exists>
{
    // Code.
}

The compiler would put all versions in the same automata and thus generate the switch.

But back to the point about variables. They WOULD need the explicit automata specification for fallback, since they can have different names. So I'd say allow that <automata:> syntax for functions as well even if it isn't needed.

It also turns out that two variables in mutually exclusive states can't have the same name. Since the documentation talks about them being a temporal scope that should be allowed.

stale[bot] commented 5 years ago

This issue has been automatically marked as stale because it has not had recent activity.