ID:1852548
 
Resolved
Using certain var names that coincide with built-in procs, e.g. block, could result in compilation errors. Many cases of this have been fixed.
BYOND Version:507.1283
Operating System:Windows 7 Home Premium 64-bit
Web Browser:Chrome 42.0.2311.135
Applies to:DM Language
Status: Resolved (513.1490)

This issue has been resolved.
I originally thought this bug was specific to lists, but I was wrong. It turned out to be a much bigger issue than I had expected. Just try defining a variable with the same name as a built-in function and set that variable to any kind of object, then see if you can call one of its methods. It doesn't compile!

This should make it clear:
someobject
proc
this_can_be_anything()
world << "This is never going to compile..."

proc
ConfuseTheParser()
var/someobject
animate = new /someobject
text = new /someobject
file = new /someobject
list = new /someobject
browse = new /someobject
icon = new /someobject
image = new /someobject
orange = new /someobject
min = new /someobject
max = new /someobject
roll = new /someobject
stat = new /someobject
view = new /someobject
//etc.

// This is the part where the compiler gets mad!
animate.this_can_be_anything()
text.this_can_be_anything()
file.this_can_be_anything()
list.this_can_be_anything()
browse.this_can_be_anything()
icon.this_can_be_anything()
image.this_can_be_anything()
orange.this_can_be_anything()
// You can just forget about eating any oranges!
min.this_can_be_anything()
max.this_can_be_anything()
roll.this_can_be_anything()
stat.this_can_be_anything()
// No stats for you!
view.this_can_be_anything()

Where you try to access the method, the compiler will throw "invalid expression" errors. It will also throw "variable defined but not used" warnings.

All of this should clearly be valid code that compiles, but it doesn't. There is some kind of bug in the parser that is ignoring everything between the dot and the left parenthesis.

Below is the original bug report for reference (List procs are not compiling when the var name is "list".):
Descriptive Problem Summary:
I have always felt paranoid about using the list procs and now I know why! I was encountering a bug without realizing it. This bug is present in the earliest build available, which is very surprising to me. How could such an obvious bug go without being fixed for years?

In reality, you cannot use any list procs for a list var when it is literally named "list". For example, list.Cut() doesn't actually work. When the name of the var is "list", list procs just don't compile, and the compiler throws invalid expression errors.

Numbered Steps to Reproduce Problem:
1. Create a new project and add the following code:
mob
verb
testcutlst() // works
var/list/lst = list("a", "b", "c")
var/pos = lst.Find("b", 1, 0)
lst.Cut(pos, pos + 1)
src << "[lst[1]]"
src << "[lst[2]]"
/*
testcutlist() // doesn't work
var/list/list = list("a", "b", "c")
var/pos = list.Find("b", 1, 0)
list.Cut(pos, pos + 1)
src << "[list[1]]"
src << "[list[2]]"
*/

2. Compile, run, click the testcutlst verb, and see that it works.

3. Uncomment the code for testcutlist() and try to compile.

4. Check for the invalid expression errors that are thrown.

Expected Results:
Naming a var "list" has no effect on compilation.

Actual Results:
Trying to call the list procs of a list var named "list" results in invalid expression compiler errors.

Does the problem occur:
Every time? Or how often?
It seems to occur every time.

In other games?
This might have been game breaking if the bug was not present in much older BYOND builds.

In other user accounts?
Definitely.

On other computers?
Yes.

When does the problem NOT occur?
It always occurs.

Did the problem NOT occur in any earlier versions? If so, what was the last version that worked? (Visit http://www.byond.com/download/build to download old versions for testing.)
The bug is present in builds as early as 354, and it doesn't seem to have ever been fixed after that. I can imagine that there might have been a much earlier build that didn't have the bug, but I have no access to any builds earlier than 354.

Workarounds:
Just don't use "list" for a variable name.
I'm going to guess this is intended behaviour, and here's my reasoning.

list is a reserved word for something special in DM, being the /list object. Trying to define it as something else is going to cause problems internally, and so BYOND just doesn't let you confuse it by throwing reserved words around in it all willy-nilly.

Granted it can be rather ambiguous, and not being a programmer in any right I personally don't get why the following would happen, again I'm sure Lummox can clarify if I'm wrong.


mob
verb
see_list()
// This compiles
var/list/list = list("a","b","c")
for(var/i in list) world << i

// This doesn't compile
if(list.Find("a"))
world << "a found"


The way I see it, if we shouldn't use list as a variable name, it should just flat-out not let us do it under any circumstance, not only when we're using specific functions.

Regardless, it gets chalked up to proper programming habits. Personally a variable shouldn't reflect its type but what the variable contains or represents, ie: list/letters = list("a", "b", "c") or list/numbers = list(1, 2, 3). Using this approach I've never come across any problems with the language.
In response to F0lak
F0lak wrote:
The way I see it, if we shouldn't use list as a variable name, it should just flat-out not let us do it under any circumstance, not only when we're using specific functions.

I have to disagree. There's no need to break existing games just because of variable names. By that logic, we shouldn't be able to name variables the same as any of the built-in types (datum, atom, mob, turf, etc.). That's not reasonable at all. There is a big difference between a built-in object type and a reserved word. Procs and verbs can be considered objects, but those are the only exceptions.

Regardless, it gets chalked up to proper programming habits. Personally a variable shouldn't reflect its type but what the variable contains or represents, ie: list/letters = list("a", "b", "c") or list/numbers = list(1, 2, 3). Using this approach I've never come across any problems with the language.

That's fine, but it isn't a good enough reason to reserve the word. I have written several procs that work with lists in a very generic sense, and I have found the name "list" to be intuitive and ideal in situations like that. Everyone has a different programming style and the language shouldn't be restricting that.

I think the only reasonable solution to this inconsistency is to allow the variable name "list" to be used in all cases.
There's an error specifically for reserved function/variable names, so that's not what's going on here.
In response to Multiverse7
I see what you're saying. I'm interested to see what Lummox has to say about it. The whole problem does seem kind of strange as far as how the program is handling it.
I haven't looked at the compiler guts behind this but my guess is that the word "list" is being interpreted as a keyword and never as a var. Likely the parser is able to understand that by var/list/list you actually want a var named list, but after that, when it sees list.Cut() it expects a . when it sees the list keyword.

The reserved word error message isn't really the same everywhere and probably just isn't setup for fringe cases like this.

I think it does merit an error message.
In response to Lummox JR
Lummox JR wrote:
I haven't looked at the compiler guts behind this but my guess is that the word "list" is being interpreted as a keyword and never as a var.

I have doubts about that, because "list" is literally never used on its own. It's either /list, which is a type, or list(), which is a proc. What use is there for a keyword that is never actually used?

Likely the parser is able to understand that by var/list/list you actually want a var named list,

Not only var/list/list, but also just var/list works fine, until list procs are used.

but after that, when it sees list.Cut() it expects a . when it sees the list keyword.

You lost me here. Why is the parser looking for another dot when it sees list.Cut()? What did you mean by that?

The reserved word error message isn't really the same everywhere and probably just isn't setup for fringe cases like this.

Is "list" actually in the list of reserved words? I have never once seen any indication of that being the case. If it is in fact a reserved word, then why isn't it highlighted and treated like all of the others?

Would it be feasible at all to revoke the keyword status, and just interpret "list" as part of a normal path? I can imagine this would have to be done anyway if /list were to ever be assimilated into a datum.

I think it does merit an error message.

If there is no other way to fix the issue, then yes, you should not be able to use "list" as a var name at all, and it should become an official highlighted keyword.
In response to Multiverse7
Multiverse7 wrote:
Lummox JR wrote:
I haven't looked at the compiler guts behind this but my guess is that the word "list" is being interpreted as a keyword and never as a var.

I have doubts about that, because "list" is literally never used on its own. It's either /list, which is a type, or list(), which is a proc. What use is there for a keyword that is never actually used?

That's exactly what I mean: it has a special meaning, and is never used alone.

but after that, when it sees list.Cut() it expects a . when it sees the list keyword.

You lost me here. Why is the parser looking for another dot when it sees list.Cut()? What did you mean by that?

Sorry, I said the wrong thing. When parsing list.Cut(), the parser must be expecting parentheses and not the dot. It's something I'd have to investigate as to how it works.

The reserved word error message isn't really the same everywhere and probably just isn't setup for fringe cases like this.

Is "list" actually in the list of reserved words? I have never once seen any indication of that being the case. If it is in fact a reserved word, then why isn't it highlighted and treated like all of the others?

It's not of the same type as for, while, etc. which are control statements.

Would it be feasible at all to revoke the keyword status, and just interpret "list" as part of a normal path? I can imagine this would have to be done anyway if /list were to ever be assimilated into a datum.

If list became a normal datum type, I'm still not sure that'd be the case.

I think it does merit an error message.

If there is no other way to fix the issue, then yes, you should not be able to use "list" as a var name at all, and it should become an official highlighted keyword.

I don't regard the current behavior as a bug except for the lack of a message; the list keyword has always been more special than, say, client, but I don't think it merits a highlight. If nothing else, highlighting it would look really weird when it's used in a path expression.
In response to Lummox JR
Lummox JR wrote:
That's exactly what I mean: it has a special meaning, and is never used alone.

I just don't see list objects as having any kind of "special meaning". The very fact that "list" is never used alone should enable its use as a var name. The compiler should be able to tell the difference between list the var, /list the type, and list() the proc. There shouldn't be any confusion.

Sorry, I said the wrong thing. When parsing list.Cut(), the parser must be expecting parentheses and not the dot. It's something I'd have to investigate as to how it works.

That's interesting. It sounds to me like the list() proc is currently not a proc at all, but is actually just one way of interpreting the same keyword. I would consider that to be a design flaw in the parser. The list() proc really should be a proc.

It's not of the same type as for, while, etc. which are control statements.

I was thinking it had more in common with proc, verb, and var, all of which are highlighted.

I don't regard the current behavior as a bug except for the lack of a message; the list keyword has always been more special than, say, client, but I don't think it merits a highlight. If nothing else, highlighting it would look really weird when it's used in a path expression.

It just seems to me like the current behavior is very inconsistent and unexpected, which can result in some ugly surprises. If you were to keep the current behavior, I think it would be necessary to have both a warning and an error message, which are going to inevitably sound really awkward. The ridiculousness of the messages should make it obvious why this inconsistency should not be there.

For example, when the user first defines a var named "list", they should be warned:
warning: list: variable name incompatible with list procs

Here's another one that sounds really funny:
warning: list: variable name unsupported for lists

When the user tries to call a list proc of a var named "list", the compiler should throw a meaningful error:
error: Cut: list is not a valid name for lists

I hope things don't end up like that, but I have to admit that it's better than how things are now, even with all the irony.

I don't think highlighting list would look weird at all, and it makes sense if you think of it as a special type of var. It looks a lot less odd than highlighting global, const, or tmp.

The point is, only going halfway in one direction or the other is not really solving the problem. Either "list" should be a reserved keyword 100% of the time, or it shouldn't be a keyword at all.
List being highlighted would look weird.

Const, tmp, global, and static are var modifiers.

Things like list, client, world, savefile are non-datum objects. They are not highlighted at all.

Verb and proc are also objects, but are so distant from any other kind of object, so it's kind of okay for them to be highlighted since they only have one purpose.

The word "list" not being able to be used when calling procs is strange though; it works as a variable, but not when trying to call a procedure (note, that it works fine for .len). I don't think list is intentionally reserved. I'm pretty sure this is legit a bug with calling procs with list.
In response to Super Saiyan X
Whether or not list looks weird when highlighted is a matter of opinion, and logic trumps opinions.

Lummox JR seems to be leaning towards making list a reserved keyword. I can't think of any reserved keywords that are not highlighted. That's basically the only indication you have of a word being reserved.

I don't support the idea of reserving the word "list". I think calling procs should be fixed for any var named "list", because that would maintain the already working functionality and that would be far more convenient than the alternative.
In response to Multiverse7
Multiverse7 wrote:
Lummox JR seems to be leaning towards making list a reserved keyword. I can't think of any reserved keywords that are not highlighted. That's basically the only indication you have of a word being reserved.

verb, proc, arg, tmp, const, static, step.

global isn't reserved either, but it acts weird at runtime because of it's dual definition.

Keywords are reserved in different scopes. There are a bunch, mostly non-datum proc names, you can't use them as procs, but you can use them as variable names.

In fact, I'm pretty sure I just realized what the issue is. It's because of the list() proc - though there isn't an error when you use it as a name. any non-datum proc is reserved (as a proc name, not a variable name); but that's not what is throwing this off. It just so happens to be that statement calls like sleep/spawn/new/del/for/etc are reserved, but those aren't functions like the others.

When you do anything like: variable.proc() - proc is ignored. It's trying to call variable() if variable also exists as a built-in function. The issue isn't list itself - but any function name used a variable name.

solution should be: fix the parser, not add them all as reserved words for variable names.
In response to Super Saiyan X
I actually meant globally reserved words, but that's all irrelevant now because you found out exactly what the problem is!

I'm so glad lists are not to blame.

I have reproduced the problem. The following does not compile. It is colliding with the built-in animate() proc.
myobject
proc
dosomething()
world << "I did something."

mob
verb
testsomething()
var/myobject/animate = new /myobject
animate.dosomething()

Just like before, I get an invalid expression error.

The bug has been found. Now we just have to crush it!
Just think. Whenever a new feature comes along with new procs, it breaks some games. I think this is a very serious bug that has been plaguing BYOND for years. We will never know how much damage it has really done.
I renamed and updated this bug report to reflect the apparently much larger scope of the bug. It was originally named:
List procs are not compiling when the var name is "list".

I'm now calling it:
Parser confusing object ref vars with built-in procs of the same name when calling vars' methods.

Please read the new report.
I do want to jump and state that if its a reserved keyword, as in, it can't be used as the name of a variable, it should be highlighted.

Blue highlighting reserved keywords is purely so developers know when they are about to name a variable a reserved thing.

Anywho, There is a good chance that list isn't a reserved keyword, so this is all moot anyway.
I'm almost certain this bug has nothing to do with reserved words. The issue that I saw with the name "list" is identical to using any other built-in proc name as the name of a var. I don't think "orange" is one of the reserved words, and since "list" has the exact same issue, whether or not it's a reserved word is not relevant. I'm sure that once this bug is fixed, we will be able to use "list" as a var name, just like all of the other problematic words.
To simplify, this is an ancient issue in which built-in proc names don't like to be used for vars.

I actually think this is okay on the parser end. As far as I can tell, the real culprit is the proc code builder.
I thought it might be something like that. I hope this isn't too hard to fix.
It will definitely be hard to fix. There's a reason this has been around forever.
Page: 1 2