-
-
Notifications
You must be signed in to change notification settings - Fork 98
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
Implement a transpiler for GDScript to C++ #3069
Comments
Hmmm, you definetly have my attention with this project. |
In my opinion, the best results can be achieved by directly dealing with GDScript's parser tree/AST, especially when it comes to maintenance. I've also done some experimental stuff using this kind of approach at Goost, see https://github.com/goostengine/goost/tree/gd3/modules/gdscript_transpiler (not in official builds). The implementation is probably quite naive and it's just proof of concept, but that's how the whole process of parsing could be simplified. This way, you don't have to re-implement GDScript tokenizer and parser yourself, but of course, this kind of approach requires compiling the engine from source. If this could be implemented directly in Godot, this would be the natural route to take. One of the difficulties I see is being able to transpile coroutines ( Another challenge/limitation is the requirement that all variables/functions must always have types explicitly defined. This might be easier to do from within C++ because GDScript parser may infer types implicitly from constants. |
Best article on pragma once I could find on short notice: https://luckyresistor.me/2019/07/13/why-its-time-to-use-pragma-once/ |
What you're describing sounds great. I'm asking out of curiosity; After converting the script you call gdpp to cpp with transpiler, will godot be able to compile it? If it can do that, can we already use cpp files (various libraries)? For example, I want to do image processing, there is a nice library written in cpp for this, it would be great to be able to add it. |
You can already achieve that by either making custom engine modules (requires a full engine recompilation with modules included, both for the editor and for the export templates), or by creating a GDNative plugin (using C/C++ binding, or any other available bindings). |
this is quite an interesting project, would that save the work from having to port GDnative or compiling the entire engine in case of modules? i really wanted an cross platform way of having C++ code in godot so i can better optimise for lower end hardware. |
yeah in that case the transpiler will work only 4.0 onwards, which is not GDNative anymore but GDExtension, also you will basically type gdscript and it will output a .cpp and .h file and will be compiled automatically by the plugin! so just type/compile/done process! |
I've been thinking on similar lines - a transpiler from gdscript to GDExtension. I was thinking on the lines of an additional "Compiled native" option to the project exporter which would:
This would allow all gdscript code to get the benefit of native execution speed - with the trade-off of a significant increase in build time, and the developer having to provide scons and compilers for all supported targets - a perfect scenario to leverage github actions. Improving the set of available container types (Vector, Queue, Fifo, Set, PriorityQueue, FixedSizedFifo, etc.) would be additional improvements which gdscript (both interpreted and compiled) could benefit from. |
I'd like to clarify that, from what you mentioned, only |
Instead of generating C++ source code, an alternative could be to generate LLVM IR directly (of course together with DWARF metadata to allow source level debugging), that can be then compiled either to native code or to WASM. The GDScript implementation in Godot 4 already has a (bytecode) generation interface, which could probably be used as a starting point. Another option would be to compile GDScript code to WASM bytecode (See proposal #3370). WASM runtimes already support interpreted, JITed and AOT compiled execution modes, with the later case reaching near-native performance. The advantage of this option over the LLVM IR output option is that it does not add LLVM as a dependency to Godot. The WASM micro runtime is less than ~100KB: https://github.com/bytecodealliance/wasm-micro-runtime In either case, this would work best with the implementation of #3369, in which case classes implemented with GDScript would always be standard GDExtension classes regardless whether they run in interpreted mode or in AOT compiled mode. Full disclosure: I submitted the mentioned proposals. |
@nonunknown Links in OP don't work (404) Also, a vote for WASM target |
@kisg llvm implementation would be pretty bloated. If you just try to go ahead & download the LLVM source code it will be 20GBs+ I had also suggested a very quick speed boost that can be gained if we transpile gdscript to lua behind the scene. |
LuaJIT's big disadvantage is that it's a JIT, which means it won't be accepted on iOS, as Calinou pointed out in your original proposal. |
@Zireael07 , as I have mentioned in the comment & my original proposal, LuaJIT with JIT off(interpreter mode) still blows every other scripting language by huge margins. Because the interpreter is hand optimized & the language is simple. JIT can be turned off with a simple directive on those platforms which don't support it. |
The linked article says:
I've seen the sideloading procedure required for JIT-enabled apps and it's something… 😶 |
Sorry for being a little flashy with my words. However, I request documenting the bytecode of GDscript. Btw, LISP is a dynamic language but it can be compiled to machine code. There are a lot of possibilities but people cannot do much because its hard to even get started because of lack of documentation. |
If you read my previous comment to the end, I suggested to emit WASM bytecode directly from the GDScript runtime, exactly to avoid the dependency on LLVM. |
More than reasonable ask. |
I take it that, it means 'reasonable++'. |
https://github.com/bruvzg/gdsdecomp has documentation on GDScript's bytecode format. |
I could not find a documentation there. The only thing I found that could be referred to, is the code itself. |
@be-thomas If you want to create a GDScript to Lua transpiler (or any other alternative backend), then probably the best way is to use the code generator abstraction already present: https://github.com/godotengine/godot/blob/8adf04804550957f43c810b13fcce66dd76e5fd8/modules/gdscript/gdscript_codegen.h The GDScript bytecode generator is just an implementation of the above interface. You don't need to use the GDScript bytecode directly, because it is an implementation detail of the GDScript VM that you are trying to replace with the LuaJIT VM. |
reference: https://programming-language-benchmarks.vercel.app/lua-vs-csharp And based on my experience in the past, luajit is unlikely to have the "almost equal" performance of C#. To clarify, I'm not saying that luajit is not good. It's excellent. But I totally don't think it's a good idea to use it as GDScript's transpiler target. Wasm is a more reasonable solution, especially considering that GDScript has no garbage collector. |
Those benchmarks are using the vanilla Lua Interpreter. It easily beats v8 & is faster than unoptimized C & C++. On what grounds, am I saying it will have "almost equal" performance of C#?
My Questions -
|
One of the Best practice for engine contributors guidelines is to only reuse libraries if it makes sense. We are intentionally self-conscious about this and want to avoid relying on third-party decisions (see Bullet shifting its focus from games to robotics and simulation).
GDScript has already received a rewrite and several optimizations for 4.0, such as typed instructions. I'm confident contributors will be able to continue this work for future 4.x releases 🙂 |
I'm curious how a general purpose programming language could shift its focus, such as to be unusable for programming. Now, really I can just keep on saying & supporting LuaJIT but it seems pretty useless now. Since, I'm the only one talking about it. People are disregarding my opinions because LuaJIT supposedly uses JIT which they don't want. It really doesn't make sense & I give up convincing you all. |
I used to use LuaJIT(not interperter) heavily in unity in my full-time work. It is not so fast in the real scene, but I respect you to keep your own point of view, the result of this problem may be greatly affected by specific conditions and is not so important. If you want to use LuaJIT as the script engine, I think you should use the GDNative/Extension to achieve this goal, and then write external tools to transpile GDScript(or just use lua). This will be an exciting project. And if your goal is like this, it is not necessary to discuss it in this repo's issues, just make a plugin. If you want Godot officially change GDScript's engine to LuaJIT, I think that is definitely a bad idea. Really need performance? You should choose the more mainstream C# or GDNative. GDScript provides excellent flexibility and does not have performance bottlenec in most scenarios. Lua is a language with GC, and it has very different design from GDScript. The great advantage of GDScript is that it is customized for Godot. Changing the script engine will definitely have an impact on this point, and at least it will increase a lot of maintenance costs. And "No GC" is very meaningful in many games (Many unity developers need to deal with GC related optimization problems all year round) |
The answer to this question is simple: it doesn't have to. GDScript do not intend and do not need to be the fastest scripts language. If the main problem is performance, Python should not exist as the most widely used language all the year round. I certainly don't mean that we should not optimize GDScript, but considering that people are working hard to do this, and that the current performance is sufficient in most scenarios, and other scenarios have other solutions, it seems unnecessary to be strict on this issue. |
I think this idea(or another "GDSciprt to binary" transpiler solutions) should be rethink. In particular, most of game engines alternative to Godot have this convenience. Game Maker Studio: Unity Godot is a engine promising the fast development process and the ease of use. Of course, GD Extension (Or Currently Gdnative) is an important solution. But do you think this is enough? Is it realistic to seek C ++ experience for users who use GDScript and want performance? When we look at Godot's user base, we do not see this depiction. I think this would be a game-changer alternative both for making GDScript more valuable and in terms of performance solutions. And I would like to thank the developer team again here. Please think about this once again. |
for those interested, I made a Gdscript to C# and c++ transpiler. |
This comment was marked as off-topic.
This comment was marked as off-topic.
@Foxchandaisuki Please don't bump issues without contributing significant new information. Use the 👍 reaction button on the first post instead. |
Describe the project you are working on
None atm
Describe the problem or limitation you are having in your project
PS: This is more a tracker than a proposal (its already being implemented). The reason for this proposal is because:
GDScript is a very pratical language, but for some things like use of external libraries or intesive operations it can be a problem.
IMPORTANT
My intention is not to ignore/hate/kill the GDScript from Godot, but instead empower the language so we can have the best of both worlds.
Describe the feature / enhancement and how it helps to overcome the problem or limitation
What if we can use gdscript with the performance and built-in types from c++ this way we can mix toguether the good and the best!
The idea came from the cumbersome process of using GDNative, where the end-user needs a lot of knowledge of building projects and also attach them to the project! Yes I know, Godot 4.0 will not have it anymore, but instead will have GDExtension which I dont know nothing about yet! (if someone could explain in the comments would be nice) But keep in mind that:
Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams
Some examples of GDPP:
The code above will be converted to the following
Myclas.hpp
Evey other thing that I didnt mentioned in the example will be exacly as GDScript itself
Project Page
The proof of concept can be found here: https://github.com/nonunknown/gdscript-pp
The link above is the old implementation for 3.x, it shows that yes, this is possible! Even its not on a usable state it can be tested to see the output, the thing is that this one read the source line by line and its not a proper language
The actual project can be found here: https://github.com/nonunknown/gdpp-standalone
It is C++17 only, and it is being implemented as actually a new programming language, at babysteps.
It already contains a tokenizer, and the parser is being done.
FAQ
Q: Why remake everything instead of just modifying godot's source?
A: I'm learning a lot doing things from ZERO (like the GDScript Tokenizer) I learned a lot and want that for the project and eveyone involved
Q: What is a
Transpiler
A: A Transpiler is program that converts source to source, instead like GDScript which converts source to bytecode
Q: This will make GDScript obsolete?
A: Nope, In any way, you will be able to use Both if you want, and use GDPP to fast prototype C++ stuff altough you can use only it!
Thanks to
This project is only possible today, because a lot of people gave me support/materials for that
@Calinou
@vnen
@willnationsdev
If this enhancement will not be used often, can it be worked around with a few lines of script?
it will be in every possible project (if the user needs or simply wants to) Where the user needs very performant code.
Is there a reason why this should be core and not an add-on in the asset library?
This atm will not be core! (maybe on the future when the project is mature)
The text was updated successfully, but these errors were encountered: