Based on commit 3e901f6d30e6b50f56686c8cc09bd1319050423a (GDScript-to-RISC-V compiler), this document provides an exhaustive list of GDScript features and their implementation status.
Features are prioritized by importance, impact, and implementation difficulty. Higher priority features should be implemented first.
These are foundational issues that should be fixed BEFORE adding new language features:
| Feature | Status | Priority Reason | Implementation Notes |
|---|---|---|---|
| Register Allocation: Core Logic | ✅ DONE | Critical infrastructure - Foundation for all register allocation | Simple Greedy Algorithm with Furthest Next Use: The allocator maintains a pool of 18 free physical registers (t0-t6, s1-s11, excluding s0/fp) and maps virtual registers to physical registers using hash maps. When allocating a register for a virtual register, it checks if already allocated (return it), spilled to stack (load it), or new (take from free pool). If the free pool is empty, it picks the virtual register with furthest next use (or unknown) as the spill candidate, stores it to stack, frees its physical register, then allocates that register to the new virtual register. This avoids stack usage when possible. The "furthest next use" heuristic tracks the next instruction position where each virtual register is used, keeping values needed soon in registers and spilling values not needed soon. Note: Stack can store things for a very long time (no limitation on arguments/storage), but registers should be preferred. |
| Register Allocation: VEVAL Handling | ✅ DONE | Critical infrastructure - VEVAL is integral for Variant operations | VEVAL syscall uses 4 registers (a0, a1, a2, a3). The register allocator handles VEVAL calls by: (1) Calling handle_syscall_clobbering() with clobbered registers (a0-a3) before the syscall, (2) Moving live values from clobbered registers to other available registers, (3) Only spilling to stack if no other registers available. The emit_variant_eval() function now automatically handles register clobbering before making the syscall. |
| Register Allocation: VCALL Handling | Critical infrastructure - VCALL is used for all method calls | VCALL syscall uses A0-A5 every invocation (6 registers total), takes an array of Variant pointers for arguments (moderate complexity), and if the return variant pointer in a5 is non-null, the return value is written back from the call. Update register allocator to: (1) Track VCALL register clobbering (a0-a5), (2) Move live values to other registers before VCALL, (3) Handle argument array construction efficiently, (4) Only spill to stack if absolutely necessary. | |
| Register Allocation: Remove a0 Stack Spill | ✅ DONE | Critical infrastructure - Unnecessary overhead | No special handling for a0 - the register allocator handles a0 like any other register. The allocator only spills to stack when necessary (no free registers available), not as a special case. |
| Register Allocation: Tests | ✅ DONE | Critical infrastructure - Verify improvements work | Created tests/tests/test_register_allocation.gd with: (1) Many Variables Test - Function with 15+ local variables (a-o) to test register pressure. (2) Complex Expression Test - Deeply nested expressions requiring many temporary registers. (3) IR verification - Tests verify functionality; IR inspection can verify max_registers <= 25 (leaving room for syscall args: VEVAL uses 4, VCALL uses 6) to ensure stack spilling is avoided. |
These should be addressed immediately after register allocation is fixed:
| Feature | Status | Priority Reason | Implementation Notes |
|---|---|---|---|
| Calling local functions | Next priority - "after this we can take a look at calling local functions" | Fix function call resolution between functions - may be related to register allocation. User: "after this we can take a look at calling local functions, maybe" | |
| Call operator (.) for Variant methods | API access - Enable calling methods on Variants via . operator |
Support call operator syntax for Variant method calls (e.g., variant.method()). Currently MemberCallExpr exists but may need enhancement for Variant methods specifically. Note: Calling member methods is done using the VCALL system call (fwsgonzo). VCALL uses A0-A5 every invocation (6 registers total), takes an array of Variant pointers for arguments (moderate complexity), and if the return variant pointer in a5 is non-null, the return value is written back from the call. This makes register allocation even more critical. See: https://github.com/libriscv/godot-sandbox/blob/compiler/src/sandbox_syscalls.cpp#L100-L159. User: "possibility of supporting the call operator (.) so that we can call methods on Variants" |
Note: The items listed below are placeholders. Priority and order are to be determined after P0 and P0.5a are complete. (iFire: "the stuff after Calling local functions and Call operator (.) for Variant methods is nonsense" - needs proper prioritization)
| Feature | Status | Priority Reason | Implementation Notes |
|---|---|---|---|
Array literals: [1, 2, 3] |
❌ NOT DONE | Extremely common - Used in almost every script | Parser + AST + CodeGen for array construction |
Dictionary literals: {"key": "value"} |
❌ NOT DONE | Extremely common - Used in almost every script | Parser + AST + CodeGen for dictionary construction |
| For loops (general iterables) | Currently only range() works - blocks array/dict iteration |
Extend gen_for() to handle Array/Dictionary iteration |
|
Const variables: const x = 10 |
❌ NOT DONE | Common practice - Simple to implement | Add const keyword to lexer/parser |
| Default parameter values | ❌ NOT DONE | Very common - Used in most function definitions | Extend parameter parsing to support defaults |
| Classes | ❌ NOT DONE | Foundation for OOP - Enables properties, methods, inheritance | Major feature - requires class system design |
| Properties/Exports | ❌ NOT DONE | Godot integration - Essential for editor integration | Property system + @export annotation parsing |
| Match statements | ❌ NOT DONE | Can wait - Defer until register allocation fixed | Full parser + AST + CodeGen (fwsgonzo: skeptical about adding features before register alloc fixed) |
These features add significant value and are commonly used:
| Feature | Status | Priority Reason | Implementation Notes |
|---|---|---|---|
| Static typing (type hints) | ❌ NOT DONE | User priority - Performance + safety | Type annotation parsing + type checking |
| Lambdas/Callables | ❌ NOT DONE | Enables signals - Functional programming | Lambda syntax + Callable type support |
| Signals | ❌ NOT DONE | User priority - Event-driven programming | Signal declaration + emit + connect |
In operator: x in array |
❌ NOT DONE | Common pattern - Membership testing | Binary operator + variant membership check |
Is operator: x is Type |
❌ NOT DONE | Type checking - Works with static typing | Type checking operator |
As operator: x as Type |
❌ NOT DONE | Type casting - Works with static typing | Type casting operator |
| Recursive functions | IR supports it - Just needs testing | Verify and test recursive call handling | |
| Assert statement | ❌ NOT DONE | Robustness - Important for production code | Assert statement support (GDScript has assert, but no try-catch) |
| Function calls between functions | Moved to P0 - Critical infrastructure issue | Fix function call resolution - may be related to register allocation |
These features are useful but can be delayed:
| Feature | Status | Priority Reason | Implementation Notes |
|---|---|---|---|
| Async/Await | ❌ NOT DONE | User said "can be delayed" - Advanced feature | Coroutine system + async/await keywords |
| Bitwise operators | ❌ NOT DONE | Specialized use - Not commonly needed | Add bitwise ops to BinaryExpr |
| Enums | ❌ NOT DONE | Type system - Works with static typing | Enum declaration + type system integration |
| Preload | ❌ NOT DONE | Optimization - Load is already available | Compile-time resource loading |
| Multi-line comments | ❌ NOT DONE | Convenience - Single-line works | Lexer support for ## ... ## |
| Documentation comments | ❌ NOT DONE | Documentation - Not critical for functionality | Doc comment parsing |
| Advanced annotations | ❌ NOT DONE | Editor features - Can use basic @export first | Various @export_* annotations |
| Static variables | ❌ NOT DONE | Class feature - Depends on classes | Static variable storage |
| Variadic functions | ❌ NOT DONE | Advanced - Not commonly used | Variable argument handling |
| Named parameters | ❌ NOT DONE | Convenience - Positional works | Parameter name matching |
🔴 P0 (Critical Infrastructure): 5 subtasks - Fix this FIRST before adding features
- Register Allocation: Core Logic - Make register allocator register-aware. System has 31 registers available. Should move to OTHER registers first, ONLY spill to stack if there is literally no other choice.
- Register Allocation: VEVAL Handling - VEVAL syscall uses 4 registers (a0-a3), a0 is return value. Handle register clobbering properly.
- Register Allocation: VCALL Handling - VCALL syscall uses A0-A5 every invocation (6 registers total), takes an array of Variant pointers for arguments. Handle register clobbering and argument array construction efficiently.
- Register Allocation: Remove a0 Stack Spill - Remove unnecessary special case where a0 is always saved to stack. Use other registers instead.
- Register Allocation: Tests - Create test file with many variables test, complex expression test, and IR verification to ensure stack spilling is avoided.
🟠 P0.5a (Next After Register Allocation): 2 features - Address immediately after register alloc is fixed
- Calling local functions - Fix function call resolution between functions (user: "after this we can take a look at calling local functions, maybe")
- Call operator (.) for Variant methods - Enable calling methods on Variants via
.operator (user: "possibility of supporting the call operator (.) so that we can call methods on Variants")
🟠 P0.5b (Language Features - To Be Prioritized): 6 features - Priority and order TBD after P0 and P0.5a are complete (iFire: "the stuff after Calling local functions and Call operator (.) for Variant methods is nonsense" - needs proper prioritization)
- Array/Dictionary literals (most common syntax)
- For loops with iterables (unlocks iteration)
- Const variables (simple, high value)
- Default parameters (very common)
- Classes (foundation for OOP)
- Properties/Exports (Godot integration)
🟡 P1 (Medium Priority): 8 features - Add significant value
- Static typing, Lambdas, Signals, Operators (in, is, as), Assert, Recursive functions
🟢 P2 (Low Priority): 11+ features - Can be delayed
- Match statements (defer until register alloc fixed - fwsgonzo skeptical)
- Async/Await (user said can delay), Bitwise ops, Enums, Preload, Comments, Advanced annotations
Key Insight from Team Discussion: Register allocation is the critical blocker. Adding features before fixing this creates technical debt. Match statements can wait.
Features are organized in the order you would learn/implement them when starting from scratch.
| Feature | Status | Notes |
|---|---|---|
Single-line comments: # comment |
✅ DONE | Handled by lexer |
Multi-line comments: ## comment ## |
❌ NOT DONE | 🟢 P2 - No multi-line comments |
| Documentation comments | ❌ NOT DONE | 🟢 P2 - No doc comment support |
| Feature | Status | Notes |
|---|---|---|
Integer literals (42, -100) |
✅ DONE | LiteralExpr::Type::INTEGER |
Float literals (3.14, 2.5) |
✅ DONE | LiteralExpr::Type::FLOAT |
String literals ("hello", 'world') |
✅ DONE | LiteralExpr::Type::STRING |
Boolean literals (true, false) |
✅ DONE | LiteralExpr::Type::BOOL |
Null literal (null) |
✅ DONE | LiteralExpr::Type::NULL_VAL |
Array literals ([1, 2, 3]) |
❌ NOT DONE | 🟠 P0.5 - Listed as "Not Yet Implemented" |
Dictionary literals ({"key": "value"}) |
❌ NOT DONE | 🟠 P0.5 - Listed as "Not Yet Implemented" |
| Vector2 literals | ❌ NOT DONE | No vector literal syntax (but available via Variant) |
| Vector3 literals | ❌ NOT DONE | No vector literal syntax (but available via Variant) |
| Color literals | ❌ NOT DONE | No color literal syntax (but available via Variant) |
| Transform literals | ❌ NOT DONE | No transform literal syntax (but available via Variant) |
Typed arrays (Array[int]) |
❌ NOT DONE | No static typing support |
Typed dictionaries (Dictionary<String, int>) |
❌ NOT DONE | No static typing support |
| Feature | Status | Notes |
|---|---|---|
Variable declaration: var x = 10 |
✅ DONE | VarDeclStmt |
Variable assignment: x = 20 |
✅ DONE | AssignStmt |
Uninitialized variables: var x |
✅ DONE | Initialized to null/0 |
| Local scope | ✅ DONE | Scope management in CodeGenerator |
Static variables: static var x |
❌ NOT DONE | No static keyword |
Const variables: const x = 10 |
❌ NOT DONE | 🟠 P0.5 - No const keyword |
Type hints: var x: int = 10 |
❌ NOT DONE | 🟡 P1 - No static typing |
| Feature | Status | Notes |
|---|---|---|
Arithmetic: +, -, *, /, % |
✅ DONE | BinaryExpr::Op::ADD/SUB/MUL/DIV/MOD |
Comparison: ==, !=, <, <=, >, >= |
✅ DONE | BinaryExpr::Op::EQ/NEQ/LT/LTE/GT/GTE |
Logical: and, or, not |
✅ DONE | BinaryExpr::Op::AND/OR, UnaryExpr::Op::NOT |
Unary: -x, not y |
✅ DONE | UnaryExpr::Op::NEG/NOT |
Assignment: = |
✅ DONE | AssignStmt |
Compound assignment: +=, -=, *=, /=, %= |
✅ DONE | Tested in test_gdscript_compiler.gd |
Bitwise: &, |, ^, ~, <<, >> |
❌ NOT DONE | 🟢 P2 - No bitwise operators |
In operator: x in array |
❌ NOT DONE | 🟡 P1 - No in operator for membership |
Is operator: x is Type |
❌ NOT DONE | 🟡 P1 - No type checking operator |
As operator: x as Type |
❌ NOT DONE | 🟡 P1 - No type casting operator |
| Feature | Status | Notes |
|---|---|---|
If statement: if condition: |
✅ DONE | IfStmt |
Elif statement: elif condition: |
✅ DONE | Handled in parse_if_stmt() |
Else statement: else: |
✅ DONE | IfStmt::else_branch |
While loop: while condition: |
✅ DONE | WhileStmt |
Break statement: break |
✅ DONE | BreakStmt |
Continue statement: continue |
✅ DONE | ContinueStmt |
Pass statement: pass |
✅ DONE | PassStmt |
| Feature | Status | Notes |
|---|---|---|
Function declaration: func name(): |
✅ DONE | FunctionDecl |
Function parameters: func add(a, b): |
✅ DONE | Parameter struct |
Function calls: add(1, 2) |
✅ DONE | CallExpr |
Return statement: return value |
✅ DONE | ReturnStmt |
Return without value: return |
✅ DONE | ReturnStmt with null value |
| Default parameter values | ❌ NOT DONE | 🟠 P0.5 - No default arguments |
Named parameters: func(x=1, y=2) |
❌ NOT DONE | 🟢 P2 - No named arguments |
Variadic functions: func sum(...args) |
❌ NOT DONE | 🟢 P2 - No variadic support |
Return type hints: func add() -> int: |
❌ NOT DONE | 🟡 P1 - No static typing |
Parameter type hints: func add(a: int, b: int): |
❌ NOT DONE | 🟡 P1 - No static typing |
Static functions: static func name(): |
❌ NOT DONE | 🟢 P2 - No static keyword |
| Virtual functions | ❌ NOT DONE | No class system |
| Overriding functions | ❌ NOT DONE | No inheritance |
| Recursive functions | 🟡 P1 - IR supports it, but not fully tested |
| Feature | Status | Notes |
|---|---|---|
Class declaration: class Name: |
❌ NOT DONE | Listed as "Not Yet Implemented" |
Class inheritance: extends BaseClass |
❌ NOT DONE | No class system |
Class instantiation: var obj = Class.new() |
❌ NOT DONE | No class system |
| Instance variables | ❌ NOT DONE | No class system |
| Instance methods | ❌ NOT DONE | No class system |
Class variables: static var x |
❌ NOT DONE | No class system |
Class methods: static func name(): |
❌ NOT DONE | No class system |
| Inner classes | ❌ NOT DONE | No class system |
| Abstract classes | ❌ NOT DONE | No class system |
| Virtual methods | ❌ NOT DONE | No class system |
| Method overriding | ❌ NOT DONE | No inheritance |
Super keyword: super.method() |
❌ NOT DONE | No inheritance |
Self keyword: self.property |
❌ NOT DONE | No class system |
Constructor: _init() |
❌ NOT DONE | No class system |
Destructor: _exit_tree() |
❌ NOT DONE | No class system |
| Feature | Status | Notes |
|---|---|---|
Property declaration: var x: int |
❌ NOT DONE | No class system |
Property getter: var x: get = get_x |
❌ NOT DONE | Listed as "Not Yet Implemented" |
Property setter: var x: set = set_x |
❌ NOT DONE | Listed as "Not Yet Implemented" |
Property getter/setter: var x: get = get_x, set = set_x |
❌ NOT DONE | No property support |
Export annotation: @export var x: int |
❌ NOT DONE | Listed as "Not Yet Implemented" |
Export group: @export_group("Group") |
❌ NOT DONE | No annotation support |
Export subgroup: @export_subgroup("Sub") |
❌ NOT DONE | No annotation support |
Export range: @export_range(0, 100) var x |
❌ NOT DONE | No annotation support |
Export enum: @export_enum("A", "B") var x |
❌ NOT DONE | No annotation support |
Export file: @export_file var path |
❌ NOT DONE | No annotation support |
Export dir: @export_dir var path |
❌ NOT DONE | No annotation support |
Export multiline: @export_multiline var text |
❌ NOT DONE | No annotation support |
Export placeholder: @export_placeholder var text |
❌ NOT DONE | No annotation support |
Export color no alpha: @export_color_no_alpha var color |
❌ NOT DONE | No annotation support |
Export flags: @export_flags var flags |
❌ NOT DONE | No annotation support |
Export flags 2D: @export_flags_2d_* |
❌ NOT DONE | No annotation support |
Export flags 3D: @export_flags_3d_* |
❌ NOT DONE | No annotation support |
Onready annotation: @onready var node |
❌ NOT DONE | Listed as "Not Yet Implemented" |
Tool annotation: @tool |
❌ NOT DONE | No annotation support |
Export category: @export_category("Cat") |
❌ NOT DONE | No annotation support |
| Feature | Status | Notes |
|---|---|---|
Signal declaration: signal my_signal |
❌ NOT DONE | Listed as "Not Yet Implemented" |
Signal with parameters: signal hit(damage: int) |
❌ NOT DONE | No signal support |
Signal emission: emit_signal("name", args) |
❌ NOT DONE | No signal support |
Signal connection: obj.connect("signal", callback) |
❌ NOT DONE | No signal support |
Signal disconnection: obj.disconnect("signal", callback) |
❌ NOT DONE | No signal support |
| Signal is_connected check | ❌ NOT DONE | No signal support |
Await signal: await signal_name |
❌ NOT DONE | No async/await support |
| Feature | Status | Notes |
|---|---|---|
Lambda functions: func(x): return x * 2 |
❌ NOT DONE | Listed as "Not Yet Implemented" |
Callable creation: Callable(obj, "method") |
❌ NOT DONE | No callable syntax |
Callable from function: Callable(self, "func_name") |
❌ NOT DONE | No callable syntax |
Callable binding: callable.bind(args) |
❌ NOT DONE | No callable support |
| First-class functions | ❌ NOT DONE | Functions can't be assigned to variables |
| Feature | Status | Notes |
|---|---|---|
Async functions: func async_func(): |
❌ NOT DONE | Listed as "Not Yet Implemented" |
Await keyword: await some_operation() |
❌ NOT DONE | Listed as "Not Yet Implemented" |
| Coroutines | ❌ NOT DONE | No coroutine support |
| Yield (deprecated) | ❌ NOT DONE | No yield support |
| Feature | Status | Notes |
|---|---|---|
For loop: for i in range(n): |
✅ DONE | ForStmt - Working (tested) |
| For loop (general iterables) | 🟠 P0.5 - Only range() supported, not general iterables |
|
Array iteration: for item in array: |
🟠 P0.5 - Only range() works, not arrays |
|
Dictionary iteration: for key in dict: |
❌ NOT DONE | 🟠 P0.5 - No dictionary iteration |
| Feature | Status | Notes |
|---|---|---|
Array literals: [1, 2, 3] |
❌ NOT DONE | Listed as "Not Yet Implemented" |
Dictionary literals: {"key": "value"} |
❌ NOT DONE | Listed as "Not Yet Implemented" |
Array indexing: arr[0] |
✅ DONE | IndexExpr - compiles to variant ops |
Dictionary access: dict["key"] |
✅ DONE | Via indexing - IndexExpr |
| Array methods (push_back, pop_back, etc.) | ✅ DONE | All Array methods available via Variant.callp() |
| Dictionary methods (keys, values, etc.) | ✅ DONE | All Dictionary methods available via Variant.callp() |
Array iteration: for item in array: |
Only range() works, not arrays |
|
Dictionary iteration: for key in dict: |
❌ NOT DONE | No dictionary iteration |
| Packed arrays (PackedByteArray, etc.) | ✅ DONE | Available via Variant - Can create and use via method calls |
| Typed arrays | ❌ NOT DONE | No static typing syntax |
| Feature | Status | Notes |
|---|---|---|
Member access: obj.property |
✅ DONE | MemberCallExpr with empty args |
Method calls: obj.method(args) |
✅ DONE | MemberCallExpr - compiles to VCALL syscall (fwsgonzo) |
Chained calls: obj.get_node().method() |
✅ DONE | Expression nesting supported |
Null-safe access: obj?.property |
❌ NOT DONE | No null-safe operator |
| Any Variant method | ✅ DONE | All Variant types support method calls - Array, Dictionary, String, Object, etc. |
| Feature | Status | Notes |
|---|---|---|
| Vector2 type | ✅ DONE | Available via Variant - Can create and use via Variant.callp() |
| Vector3 type | ✅ DONE | Available via Variant - Can create and use via Variant.callp() |
| Vector2i type | ✅ DONE | Available via Variant - Can create and use via Variant.callp() |
| Vector3i type | ✅ DONE | Available via Variant - Can create and use via Variant.callp() |
| Color type | ✅ DONE | Available via Variant - Can create and use via Variant.callp() |
| Transform2D type | ✅ DONE | Available via Variant - Can create and use via Variant.callp() |
| Transform3D type | ✅ DONE | Available via Variant - Can create and use via Variant.callp() |
| Rect2 type | ✅ DONE | Available via Variant - Can create and use via Variant.callp() |
| AABB type | ✅ DONE | Available via Variant - Can create and use via Variant.callp() |
| Plane type | ✅ DONE | Available via Variant - Can create and use via Variant.callp() |
| Quaternion type | ✅ DONE | Available via Variant - Can create and use via Variant.callp() |
| Basis type | ✅ DONE | Available via Variant - Can create and use via Variant.callp() |
| RID type | ✅ DONE | Available via Variant - Can create and use via Variant.callp() |
| NodePath type | ✅ DONE | Available via Variant - Can create and use via Variant.callp() |
| StringName type | ✅ DONE | Available via Variant - Can create and use via Variant.callp() |
| All Variant types | ✅ DONE | Full Variant type system accessible - All 40+ Variant types supported |
| Feature | Status | Notes |
|---|---|---|
Match statement: match value: |
❌ NOT DONE | 🟢 P2 - Listed as "Not Yet Implemented" (defer until register alloc fixed) |
| Match patterns (literals, ranges, etc.) | ❌ NOT DONE | 🟢 P2 - No match support (defer until register alloc fixed) |
Match binding: match x: 1: var y = x |
❌ NOT DONE | 🟢 P2 - No match support (defer until register alloc fixed) |
| Switch-like behavior | ❌ NOT DONE | 🟢 P2 - No match support (defer until register alloc fixed) |
| Feature | Status | Notes |
|---|---|---|
Type hints: var x: int |
❌ NOT DONE | Listed as "Not Yet Implemented" |
Return type hints: func f() -> String: |
❌ NOT DONE | Listed as "Not Yet Implemented" |
Parameter type hints: func f(x: int): |
❌ NOT DONE | Listed as "Not Yet Implemented" |
| Type inference | ❌ NOT DONE | No type system |
Type checking: is operator |
❌ NOT DONE | No type checking |
Type casting: as operator |
❌ NOT DONE | No type casting |
Typed arrays: Array[int] |
❌ NOT DONE | No typed collections |
Typed dictionaries: Dictionary<String, int> |
❌ NOT DONE | No typed collections |
| Generic types | ❌ NOT DONE | No generics |
| Feature | Status | Notes |
|---|---|---|
Class declaration: class Name: |
❌ NOT DONE | Listed as "Not Yet Implemented" |
Class inheritance: extends BaseClass |
❌ NOT DONE | No class system |
Class instantiation: var obj = Class.new() |
❌ NOT DONE | No class system |
| Instance variables | ❌ NOT DONE | No class system |
| Instance methods | ❌ NOT DONE | No class system |
Class variables: static var x |
❌ NOT DONE | No class system |
Class methods: static func name(): |
❌ NOT DONE | No class system |
| Inner classes | ❌ NOT DONE | No class system |
| Abstract classes | ❌ NOT DONE | No class system |
| Virtual methods | ❌ NOT DONE | No class system |
| Method overriding | ❌ NOT DONE | No inheritance |
Super keyword: super.method() |
❌ NOT DONE | No inheritance |
Self keyword: self.property |
❌ NOT DONE | No class system |
Constructor: _init() |
❌ NOT DONE | No class system |
Destructor: _exit_tree() |
❌ NOT DONE | No class system |
| Feature | Status | Notes |
|---|---|---|
Property declaration: var x: int |
❌ NOT DONE | No class system |
Property getter: var x: get = get_x |
❌ NOT DONE | Listed as "Not Yet Implemented" |
Property setter: var x: set = set_x |
❌ NOT DONE | Listed as "Not Yet Implemented" |
Property getter/setter: var x: get = get_x, set = set_x |
❌ NOT DONE | No property support |
Export annotation: @export var x: int |
❌ NOT DONE | Listed as "Not Yet Implemented" |
Export group: @export_group("Group") |
❌ NOT DONE | No annotation support |
Export subgroup: @export_subgroup("Sub") |
❌ NOT DONE | No annotation support |
Export range: @export_range(0, 100) var x |
❌ NOT DONE | No annotation support |
Export enum: @export_enum("A", "B") var x |
❌ NOT DONE | No annotation support |
Export file: @export_file var path |
❌ NOT DONE | No annotation support |
Export dir: @export_dir var path |
❌ NOT DONE | No annotation support |
Export multiline: @export_multiline var text |
❌ NOT DONE | No annotation support |
Export placeholder: @export_placeholder var text |
❌ NOT DONE | No annotation support |
Export color no alpha: @export_color_no_alpha var color |
❌ NOT DONE | No annotation support |
Export flags: @export_flags var flags |
❌ NOT DONE | No annotation support |
Export flags 2D: @export_flags_2d_* |
❌ NOT DONE | No annotation support |
Export flags 3D: @export_flags_3d_* |
❌ NOT DONE | No annotation support |
Onready annotation: @onready var node |
❌ NOT DONE | Listed as "Not Yet Implemented" |
Tool annotation: @tool |
❌ NOT DONE | No annotation support |
Export category: @export_category("Cat") |
❌ NOT DONE | No annotation support |
| Feature | Status | Notes |
|---|---|---|
Signal declaration: signal my_signal |
❌ NOT DONE | Listed as "Not Yet Implemented" |
Signal with parameters: signal hit(damage: int) |
❌ NOT DONE | No signal support |
Signal emission: emit_signal("name", args) |
❌ NOT DONE | No signal support |
Signal connection: obj.connect("signal", callback) |
❌ NOT DONE | No signal support |
Signal disconnection: obj.disconnect("signal", callback) |
❌ NOT DONE | No signal support |
| Signal is_connected check | ❌ NOT DONE | No signal support |
Await signal: await signal_name |
❌ NOT DONE | No async/await support |
| Feature | Status | Notes |
|---|---|---|
Lambda functions: func(x): return x * 2 |
❌ NOT DONE | Listed as "Not Yet Implemented" |
Callable creation: Callable(obj, "method") |
❌ NOT DONE | No callable syntax |
Callable from function: Callable(self, "func_name") |
❌ NOT DONE | No callable syntax |
Callable binding: callable.bind(args) |
❌ NOT DONE | No callable support |
| First-class functions | ❌ NOT DONE | Functions can't be assigned to variables |
| Feature | Status | Notes |
|---|---|---|
Async functions: func async_func(): |
❌ NOT DONE | Listed as "Not Yet Implemented" |
Await keyword: await some_operation() |
❌ NOT DONE | Listed as "Not Yet Implemented" |
| Coroutines | ❌ NOT DONE | No coroutine support |
| Yield (deprecated) | ❌ NOT DONE | No yield support |
| Feature | Status | Notes |
|---|---|---|
Assert statement: assert condition |
❌ NOT DONE | 🟡 P1 - No assert support |
| Error handling | ❌ NOT DONE | No error handling |
Push error: push_error("msg") |
❌ NOT DONE | No error functions |
Push warning: push_warning("msg") |
❌ NOT DONE | No warning functions |
| Feature | Status | Notes |
|---|---|---|
| @export annotation | ❌ NOT DONE | Listed as "Not Yet Implemented" |
| @onready annotation | ❌ NOT DONE | Listed as "Not Yet Implemented" |
| @tool annotation | ❌ NOT DONE | No annotation support |
| @export_* annotations | ❌ NOT DONE | No annotation support |
| Preprocessor directives | ❌ NOT DONE | No preprocessor |
| Feature | Status | Notes |
|---|---|---|
| get_node() calls | ✅ DONE | Via ECALL_GET_NODE syscall |
| print() function | ✅ DONE | Via ECALL_PRINT syscall |
| Node methods | ✅ DONE | All Node methods accessible via Variant.callp() |
| Scene tree access | ✅ DONE | Available - Can access scene tree via Object methods |
| Resource loading | ✅ DONE | Via ECALL_LOAD syscall |
| Input handling | ✅ DONE | Available - Input class methods accessible via Variant |
| Rendering API | ✅ DONE | Available - All rendering classes accessible via Variant |
| Physics API | ✅ DONE | Available - All physics classes accessible via Variant |
| Audio API | ✅ DONE | Available - All audio classes accessible via Variant |
| Networking API | ✅ DONE | Available - All networking classes accessible via Variant |
| File system API | ✅ DONE | Available - FileAccess, DirAccess accessible via Variant |
| OS API | ✅ DONE | Available - OS class methods accessible via Variant |
| Any Godot class method | ✅ DONE | Full Godot API accessible - Any method on any class via Variant.callp() |
| ClassDB instantiation | ✅ DONE | Via ECALL_NODE_CREATE with CREATE_CLASSDB |
| Object property get/set | ✅ DONE | Via ECALL_OBJ_PROPERTY_GET/SET |
| Object method calls | ✅ DONE | Via ECALL_OBJ_CALLP |
| Feature | Status | Notes |
|---|---|---|
Enums: enum Name { VALUE } |
❌ NOT DONE | 🟢 P2 - No enum support |
Constants: const NAME = value |
❌ NOT DONE | 🔴 P0 - No const keyword (note: different from const variables) |
Preload: preload("res://path") |
❌ NOT DONE | No preload support |
Load: load("res://path") |
✅ DONE | Via ECALL_LOAD syscall |
Resource paths: res://, user:// |
❌ NOT DONE | No path constants |
Groups: add_to_group(), is_in_group() |
❌ NOT DONE | No group support |
| Autoload singletons | ❌ NOT DONE | No autoload support |
| Scene tree notifications | ❌ NOT DONE | No lifecycle hooks |
| Process/Physics process | ❌ NOT DONE | No built-in callbacks |
| Input callbacks | ❌ NOT DONE | No input handling |
| Coroutines | ❌ NOT DONE | No coroutine support |
| Threading | ❌ NOT DONE | No threading support |
Reflection: get_method_list(), etc. |
❌ NOT DONE | No reflection |
Based on commit 3e901f6d30e6b50f56686c8cc09bd1319050423a:
- Basic Data Types: Integers, floats, strings, booleans, null
- Basic Operators: Arithmetic, comparison, logical, unary, assignment, compound assignment
- Variables: Declaration, assignment, local scope
- Basic Control Flow: if/elif/else, while, break, continue, pass
- Functions: Declaration, parameters, calls, return
- For Loops: Working with
range()(tested and confirmed) - Member Access: Property access and method calls (via syscalls)
- Array Indexing:
arr[index]syntax - Comments: Single-line comments
- For Loops: Only
range()supported, not general iterables - Collections: Indexing works, but no literals (methods fully accessible)
- String Operations: Basic operations work, but no multiline/interpolation syntax
- Classes & OOP: No class system at all
- Properties & Exports: No property system or annotations
- Signals & Events: No signal support
- Lambdas & Callables: No lambda or callable syntax
- Async/Await: No coroutine or async support
- Static Typing: No type hints or type system
- Match Statements: No pattern matching
- Collection Literals: No array/dictionary literal syntax (but methods work)
- Error Handling: No assert (GDScript has assert but compiler doesn't support it yet)
- Annotations: No @export, @onready, @tool, etc.
- Advanced Features: No enums, const, preload, groups, etc.
The following features were mentioned in the priority list:
- Status: DONE (Confirmed working in tests)
- Evidence from commit:
ForStmtAST node exists (src/gdscript/compiler/ast.h:158)- Parser supports
for variable in iterable:(src/gdscript/compiler/parser.cpp:169-179) - Code generator implements
gen_for()(src/gdscript/compiler/codegen.cpp:202) - Multiple test cases exist (
src/gdscript/compiler/tests/test_integration.cpp:513-835) - Working test example (
tests/tests/test_gdscript_compiler.gd:10-12):This test passes and returns correct results (e.g.,func sum1(n): var total = 0 for i in range(n): total += i return total
sum1(10) = 45) - Currently supports
range()calls only (not general iterables)
- Implementation: For loops are desugared into while loops with range iteration
- Note: Despite being listed under "Not Yet Supported" in the priority list, for loops ARE actually implemented and working
- Status: NOT DONE (Confirmed not implemented)
- Evidence from commit:
- Listed in "Not Yet Implemented" section (
src/gdscript/compiler/GDSCRIPT_COMPILER_IMPLEMENTATION.md:183) - No
MatchStmtAST node inast.h - No parser support for
matchkeyword (noparse_match_stmt()in parser) - No codegen support (no
gen_match()function) - No tests
- No token type for
MATCHkeyword
- Listed in "Not Yet Implemented" section (
- Note: Despite being mentioned as "was mentioned done", match statements are NOT implemented
- Status: NOT DONE (in GDScript compiler)
- Evidence from commit:
- Listed in "Not Yet Implemented" section (
src/gdscript/compiler/GDSCRIPT_COMPILER_IMPLEMENTATION.md:188-189) - No property getters/setters support
- No
@exportannotation support - No
@onreadyannotation support
- Listed in "Not Yet Implemented" section (
- Note: Properties work for C++/Rust/Zig programs via
add_property(), but NOT for GDScript compilation
- Status: NOT DONE (in GDScript compiler)
- Evidence from commit:
- Listed in "Not Yet Implemented" section (
src/gdscript/compiler/GDSCRIPT_COMPILER_IMPLEMENTATION.md:185-187) - No lambda function support
- No signal support
- No callable syntax in GDScript
- Listed in "Not Yet Implemented" section (
- Note: Callables/Signals work for C++/Rust/Zig programs, but NOT for GDScript compilation
- Status: NOT DONE
- Evidence from commit:
- Listed in "Not Yet Implemented" section (
src/gdscript/compiler/GDSCRIPT_COMPILER_IMPLEMENTATION.md:180) - No class definition syntax
- No object instantiation
- No method-to-property association
- The
(object, array, dictionary) int to slot systemmentioned is not implemented
- Listed in "Not Yet Implemented" section (
- What exists: Only standalone functions, no class system
- Status: PARTIALLY DONE (via syscalls, not direct API)
- Evidence from commit:
- Method calls compile to syscalls (
src/gdscript/compiler/GDSCRIPT_COMPILER_IMPLEMENTATION.md:174) - Member access
obj.method(args)works via syscall interface - Array indexing
arr[0]compiles to variant operations
- Method calls compile to syscalls (
- What's missing:
- No direct Godot class access in GDScript
- Must use syscall interface for all Godot API access
- Limited compared to full GDScript API
- Status: NOT DONE
- Evidence from commit:
- Array/Dictionary literals
[],{}listed as "Not Yet Implemented" (src/gdscript/compiler/GDSCRIPT_COMPILER_IMPLEMENTATION.md:184) - No custom data structure support
- Only basic types (int, float, string, bool, null) supported
- Array/Dictionary literals
- Status: NOT DONE
- Evidence from commit:
- Listed in "Not Yet Implemented" section (
src/gdscript/compiler/GDSCRIPT_COMPILER_IMPLEMENTATION.md:186) - No async/await syntax
- No coroutine support
- No async function compilation
- Listed in "Not Yet Implemented" section (
- Status: NOT DONE
- Evidence from commit:
- Listed in "Not Yet Implemented" section (
src/gdscript/compiler/GDSCRIPT_COMPILER_IMPLEMENTATION.md:181) - No type annotations (
: int,-> String) - No static type checking
- No register machine optimization for type hints
- All variables are dynamically typed (Variant)
- Listed in "Not Yet Implemented" section (
| Feature | Status | Notes |
|---|---|---|
| For loops | ✅ DONE | Working - Tested and confirmed in test_gdscript_compiler.gd |
| Match statements | ❌ NOT DONE | Not implemented (despite being "mentioned done") |
| Properties | ❌ NOT DONE | No property getters/setters in GDScript |
| Exports | ❌ NOT DONE | No @export annotation support |
| Classes | ❌ NOT DONE | No class definition syntax |
| Lambdas | ❌ NOT DONE | No lambda function support |
| Signals | ❌ NOT DONE | No signal support in GDScript compiler |
| Godot API | Via syscalls only, not direct API | |
| Advanced data structures | ❌ NOT DONE | No Array/Dictionary literals |
| Await/Async | ❌ NOT DONE | Not implemented |
| Static typing | ❌ NOT DONE | No type annotations (: int, -> String) |
-
For loops ARE implemented and WORKING ✅
- Full parser, AST, codegen, and test support
- Confirmed working in
tests/tests/test_gdscript_compiler.gdwithfor i in range(n): - Currently only supports
range()calls, not general iterables - Despite being listed under "Not Yet Supported" in the priority list, they ARE actually done
-
Match statements are NOT implemented ❌
- Despite being mentioned as "was mentioned done", they are NOT implemented
- No AST node, parser support, codegen, or tests
- Explicitly listed as "Not Yet Implemented" in documentation
-
Most features are NOT implemented - The GDScript compiler is a basic implementation with:
- ✅ Functions, variables, if/while/for loops
- ✅ Basic expressions and operators
- ❌ Classes, match, properties, exports, lambdas, async, static typing
-
This is a GDScript-to-RISC-V compiler - It compiles GDScript source to RISC-V ELF binaries, not a runtime feature of the sandbox itself.
-
The compiler is WIP - The commit message says "WIP: GDScript-to-RISC-V", indicating it's work in progress.
Total Features Listed: ~150+ GDScript features
Implemented: ~60+ features (40%)
- Basic data types (5)
- Basic operators (11)
- Basic control flow (8)
- Functions (5)
- For loops (1) - Working and tested
- Full Variant API (~30+ features) - All Variant types and methods accessible via
Variant.callp() - Full Godot API (~10+ features) - All Godot classes accessible via method calls
Partially Implemented: ~5 features (3%)
- For loops (general iterables)
- Collections (indexing works, but no literals)
- String operations (methods work, but no multiline/interpolation syntax)
Not Implemented: ~85+ features (57%)
- All class/OOP features
- All property/export features
- All signal/event features
- All async/await features
- All static typing features
- Collection literals (syntax only - methods work)
- Advanced language features
There's a discrepancy between the priority list (which says "For loops (was mentioned done)" and "Match statements (was mentioned done)" under "Not Yet Supported") and the actual implementation:
- For loops: Listed as "Not Yet Supported" but ARE actually implemented and working (confirmed by tests in
test_gdscript_compiler.gd) - Match statements: Listed as "Not Yet Supported" and ARE NOT implemented (no code exists)
The compiler provides access to the FULL Godot API via Variant method calls, even if direct syntax isn't supported:
- ✅ All Variant types (40+ types) are accessible: Vector2, Vector3, Color, Transform, Array, Dictionary, String, etc.
- ✅ All Variant methods are callable via
Variant.callp("method_name", args) - ✅ All Godot class methods are accessible via
obj.method(args)which compiles toECALL_VCALL - ✅ All built-in types can be created and manipulated via method calls
- ✅ Full API surface area - Any method on any Godot class is accessible
What's missing is syntax sugar, not functionality:
- ❌ Can't write
[1, 2, 3]but can callArray().push_back(1).push_back(2).push_back(3) - ❌ Can't write
{"key": "value"}but can callDictionary().set("key", "value") - ❌ Can't write
Vector2(1, 2)but can create via method calls - ❌ Can't use type hints but can use all types via Variant
The GDScript-to-RISC-V compiler in commit 3e901f6d30e6b50f56686c8cc09bd1319050423a implements:
- ✅ Function-based programming (no classes)
- ✅ Basic control flow (if/while/for)
- ✅ Basic expressions and operators
- ✅ Variable management
- ✅ Full Variant API access via method calls
- ✅ Full Godot API access via method calls
The compiler provides access to ~40% of GDScript features directly, but ~80%+ of Godot API functionality is accessible via Variant method calls. The main limitations are:
- Language syntax features (classes, properties, signals, async, etc.)
- Literal syntax (array/dictionary literals)
- Type system (static typing, type hints)
The foundation is solid, and the Variant-based API access means most Godot functionality is available, just not with the same syntax as full GDScript.
Date: December 2024
- ✅ CMake-based test suite - All compiler unit tests can be run directly using CMake/ctest
- ✅ Test coverage - Comprehensive test suite includes:
LexerTests- Tokenization and lexer functionalityParserTests- AST parsing and syntax analysisCodeGenTests- RISC-V code generationIntegrationTests- End-to-end compilation pipelinePrimitivesTests- Basic data type handlingCompilationTests- Full compilation pipeline with register allocation verification
- ✅ All tests passing - Verified on Windows with MinGW-LLVM toolchain
- ✅ Test execution:
cd src/gdscript/compiler/build && ctest --output-on-failure
- ✅ MinGW-LLVM support - GDExtension can be built using MinGW with LLVM/Clang toolchain
- ✅ Cross-platform builds - Build system supports both MSVC (with limitations) and MinGW-LLVM
- ✅ CI/CD integration - Compiler is tested in CI via integration tests in GUT framework
- Tests run in
.github/workflows/unittests.yml→buildjob - Compiler is built as part of
tests/CMakeLists.txtand linked into test ELF - Integration tests verify full compilation pipeline: GDScript → ELF → Sandbox execution
- Tests run in
- ✅ Register allocation tests - Comprehensive test coverage in
test_compilation.cpp:- Basic compilation verification
- Register allocation with 15+ variables (stress test)
- Complex expression handling
- Register spilling minimization
- Register limit enforcement (max_registers <= 25)
- Edge cases (empty functions, parameters, overlapping live ranges)
- ✅ Integration tests -
test_register_allocation.gdtests register allocation in real compilation scenarios - ✅ All compilation tests passing - 16 test cases covering register allocation and compilation pipeline
- Unit tests (ctest) - For development/debugging of compiler internals
- Integration tests (GUT) - For end-to-end verification in CI/CD
- Both approaches - Unit tests for local development, integration tests for CI verification