*bugsquad edit: * Original title was: "Can't call VisualServer.sync()"
Operating system or device - Godot version:
Godot 2.2 / 3.0
Issue description:
VisualServer.flush()
is renamed to sync()
at b524b40fdc5325c840192ce92dbed8108ccef2d9
And sync
became a keyward for high level network function.
So, now, VS.sync()
makes error Expected identifier as member
Steps to reproduce:
func _ready():
VS.sync()
VS.call("sync") # workaround
Link to minimal example project:
Just to note -- because of similar issues it is:
log
(for a logger script)dictionary.log
, dictionary.master
, dictionary.slave
, dictionary.signal
, etc.var dict = { master = get_node("master") }
(easy to workaround tho).So :+1: for that, it is a nuisance when doing normal stuff.
On to a more serious matter -- fixing it:
Currently, GDTokenizer would mark it as a keyword, not an identifier, and thus everything in GDParser which expects an identifier won't be able to use it.
One "simple" way to fix it would be to remove all references to TK_IDENTIFIER
, and replace them by a new bool GDTokenizer::is_token_identifier(int)
.
The other way would be to remove most keywords from GDTokenizer, and then check the keywords either in some new GDTokenier::is_keyword(..)
or directly in GDParser. This would lead to harder syntax highlighting for them, though.
Finally, there is a small question with both of those approaches. Consider the following GDScript:
extends Node # logger.gd
func log(prefix, string):
print("[%s] %s" % [prefix, string])
func _ready():
log("system", "Logger initialized!") # Ouch!
Should the log
call in _ready
call logger.gd::log
or @GDScript::log
? Or should declaring a function called log
be forbidden? Here are some considerations:
logger.gd::log
-- if we go with this, there is now officially no way to call the real "log", unless we expose @GDScript
directly (which isn't that bad an idea, actually). You can "vote" for it with :tada:@GDScript::log
-- if we do this, we can still call logger.gd::log
using self.log
or (if it is a singleton) Logger.log
. You can "vote" for it with :heart:func log
-- if we do this, there is now no way to make a function called log
(which would still be allowed in non-GDScript Scripts), unless we add func "log"()
or func \log()
, both of which are somewhat ugly. You can "vote" for it with :smile:I would say this isn't about names or moving stuff somewhere. It's a question of how to deal with keywords in a language.
For my C++ bindings I had to forbid some function names (like new
) and make them a valid identifier (in this case new_
because it could clash with GDScript._new()
).
ClassDB (the structure/system that holds all class and method information) is completely language independent (and with that syntax independent).
GDScript itself is just a module, it's not part of Godot's core (even though from a user perspective it kinda is).
I personally don't think that the core names should be changed so something maybe less descriptive because GDScript has a keyword like that. I think GDScript should either implement context sensitive keywords (sync
, master
and slave
are only ever valid in front of a function definition) or should document that methods that have the same name as keywords must be prefixed or anything.
I personally also think that the math functions shouldn't be keywords. Those functions shouldn't be part of the syntax, they should be part of the language's ecosystem.
Since more languages are coming anyway (C# for example), I suggest that GDScript simply deals with those names that could be keywords and documents that on the docs.
To make those special names clear in the docs I like the system a lot of Microsoft docs have:
there are tabs which show the function in the different languages (for example C#, F# and VB.NET). If the Godot docs could have a similar system then renaming problematic names wouldn't be such a big deal.
IIRC the C# binding has a lot of these exceptions because the language has so many keywords (correct me if I'm wrong @neikeq).
Just my 2 cents 馃槃
@karroffel In regards to C# reserved keywords I use @
as a prefix. e.g.: GDNativeClass.@new
. There is no problem with sync
, master
or slave
since those are attributes not keywords.
Perhaps we could add contextual keywords support to GDScript?
BTW, related/semi-dupe of #7321.
Noting down: String.match
can't be called either
Most helpful comment
Just to note -- because of similar issues it is:
log
(for a logger script)dictionary.log
,dictionary.master
,dictionary.slave
,dictionary.signal
, etc.var dict = { master = get_node("master") }
(easy to workaround tho).So :+1: for that, it is a nuisance when doing normal stuff.
On to a more serious matter -- fixing it:
Currently, GDTokenizer would mark it as a keyword, not an identifier, and thus everything in GDParser which expects an identifier won't be able to use it.
One "simple" way to fix it would be to remove all references to
TK_IDENTIFIER
, and replace them by a newbool GDTokenizer::is_token_identifier(int)
.The other way would be to remove most keywords from GDTokenizer, and then check the keywords either in some new
GDTokenier::is_keyword(..)
or directly in GDParser. This would lead to harder syntax highlighting for them, though.Finally, there is a small question with both of those approaches. Consider the following GDScript:
Should the
log
call in_ready
calllogger.gd::log
or@GDScript::log
? Or should declaring a function calledlog
be forbidden? Here are some considerations:logger.gd::log
-- if we go with this, there is now officially no way to call the real "log", unless we expose@GDScript
directly (which isn't that bad an idea, actually). You can "vote" for it with :tada:@GDScript::log
-- if we do this, we can still calllogger.gd::log
usingself.log
or (if it is a singleton)Logger.log
. You can "vote" for it with :heart:func log
-- if we do this, there is now no way to make a function calledlog
(which would still be allowed in non-GDScript Scripts), unless we addfunc "log"()
orfunc \log()
, both of which are somewhat ugly. You can "vote" for it with :smile: