-
-
Notifications
You must be signed in to change notification settings - Fork 97
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add an abstract type system for GDScript to gain access to compile-time code execution #1709
Comments
I don't think I understand this proposal. It seems to be conflating two ideas into on proposal (the abstract type system and the compile-time optimization) which are really unrelated. We could this optimization without needing the abstract part. Can you make a short concrete example of this in practice, with a full code sample? |
Ok so my understanding of how it currently works may be wrong since GDScript is dynamic, so let me first confirm that. The game on starting would encounter all 'preload' assets and load them into memory. This includes the scripts that have the When a script is being loaded it first tokenizes the strings and parses these tokens. These are stored according to properties and methods. This would be stored as a call to a native engine property/method or to another script (which would eventually chain back to a native call or simple expression?). My idea of compile-time is this process when the calls are resolved. When a script instance is executed, these calls are then made as encountered. For example So with that out of the way the basic idea is as follows: |
Just to be clear the idea is not to change how the The main reason for introducing the abstract type system is to take full advantage of the GDScript setup that currently exists during compile-time. I think calling this an abstract type system may be misleading. We could otherwise call it a Macro system. |
This sounds like you're trying to have parse-time-only data types in GDScript which, at editor-time (tool script) and runtime (game) break down to an underlying Variant-compatible data type. The main advantage of which you'd be aiming for being the achievement of improved type safety and autocompletion when writing GDScript code. Is this correct?
The improved struct and enum usability is where something like this could really shine, indeed. Although, I agree with vnen, the whole typed instructions aspect is really a perpendicular topic that is unrelated to something like this. Or rather, the proposal, as it is, is not presented in a way that caters to an effective understanding of how things work under-the-hood (understandable, given your stated experience with it).
This is an accurate assessment. Especially the use of the
I don't really understand this use case. If you want to make a wrapper, then either you are intentionally wrapping the logic of the internal class in order to add peripheral operations (in which case, you DON'T want a macro, but actually different logic executed) or you are just trying to save time by creating a GDScript class that exposes all of the same methods as the equivalent NativeScript class (which might(?) already be doable by overriding the
The code example you share here can already be emulated with a tool script perfectly. If the logic for the block under the editor hint check wouldn't work in the other context, it doesn't matter since GDScript only executes whatever logic it actually attempts to run. That is, if your logic check prevents moving into that code block, then it won't call the function and there's no need to worry something will run in an inappropriate context.
This'll get better to some degree in Godot 4 with Callback and Signal becoming part of Variant. Any references to methods or signals can now be handled with symbols rather than strings.
I don't understand why this requires an abstract type system to make the string data available via a language server of some kind. The strings can simply be exposed to the language server and triggered in the appropriate context by the language server, similar to how string-based JSON documents in VS Code can get autocompletion based on an existing JSON doc specification. The removal of stringification doesn't have any relevance to autocompletion support when it comes to language servers.
Generally speaking, core devs tend to see folders as a namespace already, i.e. the filesystem is a natural namespacing mechanism when assets and data types are, themselves, referenced via file paths. Ergo, this is a solution in search of a problem that doesn't quite exist (according to conversations I've had anyway).
A little confused here. You're saying Regardless, I have also discussed with reduz the possibility of introducing a namespace system for the global script class system (the
Regardless, I don't personally like the idea of creating a GDScript-specific solution to structs and enums like this. I think it would be better if the Variant API itself had basic support for structs as a data type where users could customize the structure of the data, ensure the data is locally allocated, and still provide full autocompletion for all keys present in the data type (potentially with typed instruction handling). For example (haven't thought this through, but...), you could have some kind of property hint info that contains a byte array Variant, a property hint indicating that it's a struct, and a property hint string that contains a breakdown of the keys, data types, and bit distributions of the data in the struct, up to 16 bytes (since Variants make up 20 bytes and 4 are reserved for the type information). Then, all user interfaces would display the "struct" similar to an object with those property names while setters and getters would directly update the appropriate bits in the byte array without any otherwise special logic. You could potentially even have a "class name" for the struct. Perhaps also a StructServer singleton that maintains information about all struct formats that have been defined so that autocompletion can be queried on an arbitrary basis rather than for a specific property. A system like this would be something that is available to all scripting languages and can have deeper integration with the user interface of the Godot Editor itself. Not saying it's a good idea. Just trying to point in a better direction. A macro system won't achieve this, and thus far I'm not convinced that a macro system is even the best solution to the use cases presented here. But I'm just one lonesome voice. Perhaps others will think otherwise. |
Describe the project you are working on:
An editor plugin. But this can help all projects using GDScript.
Describe the problem or limitation you are having in your project:
GDScript being a duck-typed language with a lot of reliance on strings, using it was sometimes very cumbersome and non-intuitive. Also, this sometimes meant not being able to use our favourite text editors. Many of the recent changes to the GDScript has been addressing this (class_name, optional-typing, signals) but it does not affect all use cases and does not make sense to radically change GDScript to a fully typed language. Nevertheless, now that optional typing has performance benefits, it makes sense to be able to take advantage of this while still having the generic nature (especially for addon and plugin development in GDScript).
Describe the feature/enhancement and how it helps to overcome the problem or limitation:
The idea is to introduce an Abstract Type System. It is loosely based on what the Haxe language does, but more streamlined towards Godot usage. The basic notion is the concept of being able to create a type that is transformed into a different type at compile time.
Let me illustrate with a few examples:
The
health
would be resolved at compile time to provide the benefits of typed optimizations while allowing the core dictionary implementation to be generic. Also, this would make value carryingenum
a possibility.SomeProjNative
, which essentially just has wrappers into the required functions. The from within GDScript you could write an abstract type to make it more useful inside GDScript.Of course, this is now possible with GDNative but requires you to create the interface completely inside the native code and making changes cumbersome. Also, GDScript is a lot easier to write code. If, as some external tool/library developer needs to support Godot I can simply do a single class with the required API translations. The library users can adapt it to however they want inside GDScript.
abstract SomeBase
is subjected to compile-time execution, if it can be resolved. Eg.This would also extend to the core code as well.
Also in many other parts of the engine, strings are extensively used. This is often prompted by the GDScript inbuilt editor, like animation clip names, preload resource string path and most importantly the
NodePath
s. Since the editor is already tracking these, we could put this data into abstract types and make it accessible, via the language server, to external text editors (I understand these are done context-sensitive i.e, which scene is open, but maybe we could cache these. Need more discussion into this). This could make it possible to have a sense of namespace using the folder structures. The current implementation ofclass_name
sort of makes the scripts be meaningfully placed in its own ' scripts' folder but this is against the Godot philosophy ob being able to place the scripts (and other resources) along with the scene file where it used, which greatly improves reusability of these scenes (especially makes a lot of sense for the addons folder stuff).Describe how your proposal will work, with code, pseudocode, mockups, and/or diagrams:
I am unfortunately not fully aware of how the internals work and hence need help to provide a concrete implementation idea.
If this enhancement will not be used often, can it be worked around with a few lines of script?:
Not really.
Is there a reason why this should be core and not an add-on in the asset library?:
It is fundamentally a new feature that needs to be in core.
The text was updated successfully, but these errors were encountered: