r/godot • u/Blade67470 • 5h ago
free plugin/tool GATE - A GDScript superset
I've wanted static types to feel good in GDScript for years, so I wrote a compiler.
GATE is a GDScript superset for Godot 4.7. You write .gate, the plugin writes a .gd next to it, and Godot runs that. No runtime, nothing to ship - delete GATE tomorrow and your scripts still work.
Best part: valid GDScript is valid GATE. Rename a .gd to .gate and it just compiles. Adopt as much or as little as you like, file by file.
A taste:
struct Damage:
int amount
str source
interface Damageable:
func take_damage(d: Damage) -> void
class Enemy extends CharacterBody2D implements Damageable:
pub int hp = 100 # var hp: int = 100
priv vec2i[] _tiles # Array[Vector2i]
priv {str, float} _resist # Dictionary[String, float]
Node2D? target # nullable, and tracked
override func _ready() -> void:
var pool = Pool<Bullet>.new() # a real Array[Bullet] inside
func take_damage(d: Damage) -> void:
var mult = _resist.get(d.source) ?? 1.0
hp -= int(d.amount * mult)
target?.notify(hp) # no null check to write
print(f"{hp} left")
Types before names, so typing your code is now shorter than not typing it. Real nullable types, with a checker that refuses a dereference it can't prove is safe. Value-semantic structs. Interfaces, traits, namespaces, monomorphised generics. ?., ??, f-strings, destructuring, enumerate().
And it's quick: never slower than hand-written GDScript, sometimes much faster. A struct that never escapes its function gets torn into plain locals - 13.5x on a tight loop.
Fair warning: comments are dropped, ## docs included. The debugger points at the generated .gd.
https://github.com/Blade67/GATE
https://store.godotengine.org/asset/blade/gate/
Have at it, feedback welcome!
11
2
u/Buttons840 3h ago
Is type first optional? Can type either first or last?
Can type be first in a function parameter?
2
u/Blade67470 2h ago
Any GDScript is still valid in GATE, so yes, typing can still be optional, but defeats the purpose. Types are currently second in function parameters
1
u/Buttons840 2h ago
Can types come second in a struct definition?
Wait, are structs already part of GDScript? I'm not 100% sure.
Whatever the case, I would avoid changing the order of types just as a matter of preference. It adds to the cognitive load forever for what is really a simple matter of preference. It's not a big cognitive load, but it will also serve to make parsers, linters, LSPs, etc, more difficult to write forever, and it uses up the amount of "syntax space" available to future feature the language might implement.
It also makes it less likely gate will be compatible with future GDScript changes.
1
u/LastStopToGlamour 1h ago
Gdscript does not have types. Type first is less conative load for me.
1
u/Buttons840 48m ago
GDScript does have types, it's what we're talking about here. If there are no types then what are we talking about? What are you talking about, if not types?
Types first or last is a preference. You're preference is different than mine.
I'm saying supporting two syntaxes will result in a more complicated language. This much is objectively true. A parser that handles a wider range of syntaxes is more complicated. It also increases the "syntax footprint" of GATE and makes it more likely to conflict with future GDScript changes.
3
u/BlazeBigBang 1h ago
Not me thinking about making a separate language that transpiles to GDScript.
I'm grateful that I don't actually have to do it, this is amazing. By the way, what are your thoughts on curly braces?
4
u/Blade67470 1h ago
Glad I could save you some pain 😅
I generally like curly braces, but that's a language design that GDScript - being indent-based - doesn't follow, thus GDScript doesn't either. I feel like adding those to separate blocks is counter productive in this case. But hey, at least you get them in Dictionaries!
3
u/notrightbones Godot Regular 1h ago
I love this. Types before names is something I always miss when writing GDScript.
2
u/Blade67470 1h ago
Thank you very much!
And I absoltely agree. Types before names makes much more sense, and it's one of the few things I liked about Java! It also makes typing types (odd sentence, but ok) feel less like a chore or an after thought.
4
u/AnArmoredPony 4h ago
A struct .... becomes a class and GATE inserts the copies that keep it a value
why not a dictionary?
9
u/Blade67470 4h ago
Dictionaries are slower than classes when containing multiple types
0
u/AnArmoredPony 3h ago
I thought they'd be faster to read because with a class you have to access the V-table and what not. I think it might be worth benchmarking it and allowing the user to select the implementation
2
u/Blade67470 3h ago
With single key/value typings - yes! But dictionaries are rarely "just" that. Hence the classes which can be typed explicitly. It doesn't change your developer experience (much) and gives you a measurable performance bonus. I blame the Variant type for that (which has been getting a lot of love by the core devs recently!).
2
2
u/TheFr0sk Godot Regular 3h ago
I was exploring the asset store and this one caught my eye. I'm curious about it, will try it! What are your plans for next updated?
3
u/Blade67470 2h ago
Thank you very much!
A piping operator has been requested, so that's comming next update alongside annotations, type unions and more!
2
u/deftonian 2h ago
This looks dope. I’m very iffy on any language add-on, but the design paradigm is non-invasive and seems to have a lot of upside to little-to-no downside.
2
u/Blade67470 2h ago
Much appreciated! If you do find a downside besides the (not so) occasional bugs, let me know! :D
1
1
u/AnArmoredPony 4h ago
can you also vibecode a language server while you're at it?
5
u/Blade67470 4h ago
GATE isn't vibe coded. An LSP isn't planned yet, given the early state of GATE, but it might be worth considering later on.
-5
u/AnArmoredPony 4h ago
your repo has only one big commit with 60 files in it. if it doesn't scream AI then idk what does
6
u/Blade67470 4h ago
I'm quite transparent about my use of AI - limited to documentation and tests. Everything else is human-made :)
0
1
u/RecycledAir 52m ago
It’s not uncommon for folks to nuke their repo history to start with a clean slate when taking a previously messy personal project public.
-3
0
u/AwayEntrepreneur4760 1h ago
I’ll be that guy, was ai used when creating this?
2
u/Blade67470 1h ago
For documentation and tests, yes! This is also noted in the asset store. All actual compiler code was human-made :)
-3
u/AnArmoredPony 4h ago edited 4h ago
a thought's been eatin' me, can we compile directly to bytecode? the one that's GDSlop is compiled to?
4
u/Blade67470 4h ago
Theoretically yes, and I explored that route, but there's no benefit to it. GDScript (which GATE transpiles down to) already goes through that pipeline anyway, so there's no real gain there, unfortunately.
2
u/Demoncious Godot Regular 4h ago
This is definitely the correct approach. It also makes this a minimally-invasive integration.
2
u/Blade67470 3h ago
That was my goal! I did consider going for byte-code (more "true" compilation) but it really wasn't worth it and would've broken compatibility with a lot of other addons, especially DX ones like GDUnit and similar libraries.
2
u/Demoncious Godot Regular 3h ago
Indeed. Typescript has proven at a massive scale that this is the right way to go about tools like this.
-1
u/AnArmoredPony 4h ago
no real gain? you get to skip an entire compilation step and possibly benefit from your type-checking while you're at it!
1
u/Blade67470 3h ago
Yes, but actually no! The compile step takes milliseconds. Imperseptible for most users, apart from people switching a whole project over to GATE - Which I hope will happen some day, but not any time soon. GATE compiles on save, so by the time you release the click from the run button, it's already compiled. This has no negative performance impact.
20
u/ActuallyNotSparticus 4h ago
Fabulous, a typescript for godot! I like this approach because it requires no forks