Skip to content

feat(frontend): lower singleton receivers and resolve inherited engine statics#49

Merged
SuperIceCN merged 11 commits into
masterfrom
frontend/fix/issue-36
Jun 27, 2026
Merged

feat(frontend): lower singleton receivers and resolve inherited engine statics#49
SuperIceCN merged 11 commits into
masterfrom
frontend/fix/issue-36

Conversation

@SuperIceCN

@SuperIceCN SuperIceCN commented Jun 27, 2026

Copy link
Copy Markdown
Collaborator

Summary

This PR extends frontend singleton and static-member resolution so singleton receivers lower through load_static, dual-role singleton bindings keep stable semantics across use sites, and inherited engine class static members resolve correctly. It also updates the C backend support required by the new lowering path, including builtin constructor runtime helpers and load_static code generation coverage.

What changed

  • Added singleton-oriented frontend semantic and lowering support so singleton receivers can materialize as static loads instead of drifting into value bindings.
  • Routed dual-role singleton lookups through updated top-binding and chain-reduction logic, including receiver/type bias handling and preserved resolved-value bindings.
  • Extended class-registry and inherited static-member lookup paths so engine class static constants and methods resolve through superclass metadata.
  • Updated backend C code generation and binding support for load_static, engine method binds, and builtin constructor runtime helpers.
  • Added runtime, lowering, semantic, scope, and backend tests covering singleton receiver calls, dual-role singleton use sites, inherited engine statics, and builtin constructor/header compilation paths.
  • Added and refreshed implementation notes under doc/module_impl/frontend and doc/module_impl/backend, plus related IR notes.

Why

  • Singleton references previously could drift between type-style and value-style interpretations across different analysis and lowering stages, which made call lowering and chain binding unstable.
  • Inherited engine static members were not resolved consistently from superclass metadata, so valid static constants/methods on engine ancestors could be missed.
  • The backend needed matching load_static and builtin-constructor support so the frontend semantic fixes could compile end to end.

Affected packages/files

  • gd.script.gdcc.frontend.sema.analyzer
  • gd.script.gdcc.frontend.sema.analyzer.support
  • gd.script.gdcc.frontend.lowering.*
  • gd.script.gdcc.scope.ClassRegistry
  • gd.script.gdcc.backend.c.gen.*
  • src/main/c/codegen/include_451/gdcc/*
  • src/test/java/gd/script/gdcc/frontend/*
  • src/test/java/gd/script/gdcc/backend/c/*
  • src/test/test_suite/unit_test/{script,validation}/runtime/*
  • doc/module_impl/frontend/frontend_singleton_implementation.md
  • doc/module_impl/backend/load_static_implementation.md

Validation

  • ./gradlew.bat classes --no-daemon --info --console=plain
  • powershell -ExecutionPolicy Bypass -File script/run-gradle-targeted-tests.ps1 -Tests FrontendTopBindingAnalyzerTest,FrontendLoweringBodyInsnPassTest,CLoadStaticInsnGenTest,CConstructInsnGenTest

Result: BUILD SUCCESSFUL

Risks / Notes

  • This PR touches both frontend semantic resolution and backend codegen. The main remaining review focus should be singleton/type-bias edge cases and load_static C emission compatibility.

Key behaviors covered (Optional)

  • Singleton receivers lower through load_static in runtime and lowering tests.
  • Dual-role singletons keep stable binding semantics across mixed type/value use sites.
  • Inherited engine class static constants resolve from superclass metadata.
  • Builtin constructor helper declarations and load_static C codegen paths are covered by targeted backend tests.

Diff stats (Optional)

  • 67 files changed, 5176 insertions, 422 deletions.

Breaking changes (Optional)

  • None

Related docs (Optional)

  • doc/gdcc_low_ir.md
  • doc/module_impl/frontend/frontend_singleton_implementation.md
  • doc/module_impl/frontend/frontend_top_binding_analyzer_implementation.md
  • doc/module_impl/backend/load_static_implementation.md
  • doc/module_impl/backend/godot_binding_implementation.md

Closes #36

- document singleton receiver lowering gaps across frontend and backend
- define the `load_static "@globalscope"` design and binding contracts
- outline phased tests, implementation steps, and acceptance criteria
- Validate singleton metadata in ClassRegistry before publishing value bindings.
- Materialize singleton identifiers as @globalscope load_static receivers and lower backend singleton reads as borrowed objects.
- Split singleton lookup and return type metadata for module-local Godot wrappers.
- Cover executable/property-init pipelines, binding usage, codegen snapshots, and LIR round-trip.
- Update frontend/backend/LIR implementation docs with completed phase status.
- Add runtime test-suite case for singleton property init, return, void, and argument calls.
- Add body-lowering guard test for published singleton bindings without registry metadata.
- Update singleton receiver lowering plan status and bundled test resource list.
- Store top-binding resolved values and access status in FrontendBinding.
- Reuse published resolved values in expression and chain receiver analysis.
- Refresh local binding payloads after slot type writeback and cover drift cases.
- Add runtime fixture for later-local shadowing and self-referential initializer drift.
- Register the new script in the unit test compile runner.
- Record the new regression coverage in the frontend lowering plan.
- Implement tryApplyDualRoleTypeMetaBias with fail-closed rules
  for constants, enums, static methods, and .new() on dual-role names
- Value-winner authority via resolveVisibleValue prevents shadowing
  override by local/param/property bindings
- Signal defensive coverage in fail-closed instance-namespace checks
- Reorder analyze(classRegistry, analysisData) to match codebase convention
- Add 20+ unit tests with custom ExtensionAPI fixtures and plan doc updates
…ss, hasEngineClassConstant into ClassRegistry

- Remove 6 duplicate private method definitions across FrontendTopBindingAnalyzer,
  FrontendChainReductionHelper, and FrontendConstructorResolutionSupport
- Route all callers through the three new public ClassRegistry methods
- Add dual_role_singleton_static_constant.gd fixture exercising
  IP/ResourceUID/DisplayServer engine class constants via TYPE_META
  static load in executable body and property initializer.
- Add dual_role_singleton_mixed_use_sites.gd fixture verifying
  SINGLETON instance call and TYPE_META static load routes do not
  pollute each other within the same body.
- Register both fixtures in EXPECTED_SCRIPT_PATHS and record
  Step 9 end-to-end validation in the lowering plan.
- Add findEngineClassEnumValue / findBuiltinClassEnumValue to ClassRegistry
- Rewire LoadStaticInsnGen, FrontendTopBindingAnalyzer, and FrontendChainReductionHelper to resolve enum values via ClassRegistry
- Mirror the new helper paths in CLoadStaticInsnGenTest and FrontendChainReductionHelperTest coverage
- Sync doc/module_impl/backend/load_static_implementation.md, frontend_chain_binding_expr_type_implementation.md, and frontend_singleton_receiver_lowering_plan.md with the routed lookups
- Walk the engine `inherits` chain in ClassRegistry for static constants and
  enum values (direct-first with cycle detection); keep builtin lookups
  direct-only to match the metadata model
- Wire the inherited lookups through dual-role bias, chain reduction, and
  backend literal emit so all three layers stay consistent
- Fix singleton fail-closed symmetry by filtering static properties in the
  instance-property hierarchy check
- Clarify engine "not found" diagnostics to mention the searched superclasses
- Add an end-to-end runtime fixture for an inherited engine class constant
- Sync affected docs and mark the prior direct-only boundary as resolved
…t source

- Rename `frontend_singleton_receiver_lowering_plan.md` to
  `frontend_singleton_implementation.md` and rewrite as long-term source
  of truth
- Drop step-by-step progress, completion status, and verification dates;
  keep only current contracts, architecture, and risk boundaries
- Strip "Step N" references from `FrontendExprTypeAnalyzer` and the
  dual-role test sections so code comments describe current behavior only
@SuperIceCN SuperIceCN merged commit 50b6a25 into master Jun 27, 2026
1 check passed
@SuperIceCN SuperIceCN deleted the frontend/fix/issue-36 branch June 27, 2026 15:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Frontend lowering cannot materialize singleton receivers into LIR

2 participants