Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ Body procedure 必须是 root-bounded、statement-local 的实现。每个 owner
- `WhileStatement`。
- `ForStatement`:header-only statement boundary 完成后,通过普通 `resolveChildSuite(...)` 进入结构完整的 `FOR_BODY`。

`MatchStatement`、`LambdaExpression` 与 block-local `const` 仍保持结构性 deferred / unsupported;它们不创建 lifecycle state,也不能因 typed result 改变 body entry。
`MatchStatement` 与 block-local `const` 仍保持结构性 deferred / unsupported;它们不创建 lifecycle state,也不能因 typed result 改变 body entry。已记录 `LambdaExpression` 已转正为 nested callable owner;未记录 lambda 保持 fail-closed

## 5. Statement 内 Owner 顺序

Expand Down Expand Up @@ -274,8 +274,8 @@ Guard 必须在 pending overlay write 时 fail-fast,不能等 suite export 时
Resolver 保留三类彼此独立的结构检查:

1. Request-domain hard boundary:只有 `EXECUTABLE_BODY` 进入 ordinary lookup。
2. AST boundary:parameter default、lambda、match 与 block-local `const` 返回精确 deferred domain;for header/body edge 已转正
3. Current-scope backstop:lambda callable/body 与 match section body 即使 AST edge 缺失也继续 fail-closed;`FOR_BODY` 是 supported executable scope。
2. AST boundary:parameter default、match 与 block-local `const` 返回精确 deferred domain;for header/body edge 与已记录 lambda AST 边已转正
3. Current-scope backstop:`MATCH_SECTION_BODY` 即使 AST edge 缺失也继续 fail-closed;`FOR_BODY` 与已记录 lambda 的 `LAMBDA_BODY` / `LAMBDA_EXPRESSION` 是 supported executable scope。未记录 lambda 保持 fail-closed

这些检查不读取 typed overlay 以决定结构支持,也没有 pending/published lifecycle。`FrontendSuiteContext` 根据 structural policy 创建 request;`FrontendSuiteResolver` 在进入 root/child body前使用 completeness certificate 验证 interface facts。Typed overlay 只改变过滤通过后的 effective type/binding payload。

Expand Down
2 changes: 1 addition & 1 deletion doc/analysis/frontend_semantic_analyzer_research_report.md
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@

1. **没有 frontend -> LIR lowering。** 当前语义主链仍止步于 side table、diagnostics 与 class skeleton;函数体不会继续产生 LIR。
2. **compile-ready 与 shared semantic 仍然分离。** `FrontendCompileCheckAnalyzer` 已经提供 compile-only final gate,但 `ConditionalExpression`、`ArrayExpression`、`DictionaryExpression`、`PreloadExpression`、`GetNodeExpression`、`CastExpression`、`TypeTestExpression` 与 `assert` 仍需要在进入 lowering 前被显式封口。
3. **若干 executable-body 域仍保持 deferred / unsupported。** 参数默认值、lambda capture、`match` pattern binding、block-local `const` 等尚未进入当前正式支持面。`for` iterator/body inventory 已在后续阶段 B/D0/L 转正,但 iteration planning 与 lowering route 仍未完成
3. **若干 executable-body 域仍保持 deferred / unsupported。** 参数默认值、`match` pattern binding、block-local `const` 等尚未进入当前正式支持面。已记录 lambda 的 param / local / capture inventory 与 compile gate 已转正。`for` iterator/body inventory 与已注册 route 的 lowering 已落地;`OBJECT_CUSTOM` 仍未注册 contract
4. **`self` 核心语义已经接通,但 signal use-site 与 coroutine 语义仍未闭环。** 当前代码已经支持 `self` 的 top binding 发布、static context fail-closed、property initializer fail-closed,以及将 `self` 解析为当前类实例 receiver;仍未形成稳定 frontend 合同的是 `.emit(...)`、`await signal` 等 signal/coroutine use-site,以及更完整的 context-sensitive diagnostics。
5. **property initializer 仍不是完整实例初始化模型。** 当前支持面是“published subtree facts”,而不是 declaration-order / default-state / cycle-aware 的 class-member initializer 语义。
6. **header superclass 的支持面仍受 MVP 限制。** path-based `extends`、autoload superclass、global-script-class superclass 与跨多个 gdcc module 的 superclass 绑定依然没有接通。
Expand Down
2 changes: 1 addition & 1 deletion doc/benchmark.md
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ Bundled benchmark case families currently cover:
Authoring constraints:

- keep compiled benchmark scripts within the currently supported frontend and backend feature set
- avoid unsupported constructs in compiled scripts such as `for`, `match`, and `lambda`
- avoid unsupported constructs in compiled scripts such as `match`; `for` and recorded `lambda` are now compile-ready, but keep new cases on already-proven surfaces unless the benchmark is specifically exercising them
- avoid array and dictionary literal patterns that compile mode still rejects
- for stateful cases, reset reusable state in `prepare()` instead of relying on cross-sample carry-over
- when `prepare()` rebuilds state, reset auxiliary counters and cached derived data there as well so
Expand Down
14 changes: 10 additions & 4 deletions doc/gdcc_low_ir.md
Original file line number Diff line number Diff line change
Expand Up @@ -246,10 +246,16 @@ $<result_id> = construct_standalone_callable "<kind>" "<owner_or_empty>" "<name>
#### construct_lambda

Constructs a new Callable from a lambda function in this compiling unit.
For implementation, `godot_callable_custom_create2` is used.
All captures are copied into a tmp struct and passed to the lambda via `callable_userdata`.
If there are no captures, NULL is passed as `callable_userdata`.
`free_func` in `GDExtensionCallableCustomInfo2` must be set to destruct the captures.
Backend uses `gdcc_new_lambda_callable` → `godot_callable_custom_create2`.
Captures are copied into a heap `${Class}_Capture_${func}` and stored as
`callable_userdata`. If there are no captures, userdata is `NULL` and
`free_func` is a no-op. With captures, `free_func` destroys each destroyable
field and then `godot_mem_free`s the block.
The generated lambda C function takes source parameters plus a trailing
`_capture` pointer when `captureCount > 0`. After locals are declared and
before `__prepare__`, the backend copies `_capture->name` into the matching
`$name` slot. Capture locals are excluded from `__prepare__` default
construction so destroyable types are not leaked.

```
$<result_id> = construct_lambda "<lambda_function_name>" $<capture1_id> $<capture2_id> ...
Expand Down
14 changes: 9 additions & 5 deletions doc/gdcc_runtime_lib.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,15 @@ extend the runtime-provided `godot_*` surface.
wrapper pointer conversion helpers, compatibility constructors, UTF-8 formatting helpers,
Variant type guards, GDScript `is` type-test helpers, Variant writeback classification and
`godot_Variant_call(...)`. It also pulls in sibling headers such as `gdcc_callable.h`.
- `gdcc_callable.h`: no-receiver custom Callables for `construct_standalone_callable`. Owns
`gdcc_new_standalone_callable`, a growable heap intern table of `gdcc_standalone_callable_spec`
(one `godot_mem_alloc` per unique `(kind, owner, name)`), custom `GDExtensionCallableCustomInfo2`
callbacks, and `ClassDB.class_call_static` forwarding. `gdcc_standalone_callable_registry_destroy_all()`
frees the table on GDExtension unload. The includer must declare `class_library` first.
- `gdcc_callable.h`: custom Callables for `construct_standalone_callable` and
`construct_lambda`. Owns `gdcc_new_standalone_callable` (growable heap intern table of
`gdcc_standalone_callable_spec`, one `godot_mem_alloc` per unique `(kind, owner, name)`,
`ClassDB.class_call_static` forwarding, `gdcc_standalone_callable_registry_destroy_all()`
on unload) and `gdcc_new_lambda_callable(userdata, object_id, call/is_valid/free/argc)`.
Lambda `object_id` is supplied by the caller from a cached fat-pointer `instance_id`
when the lambda captures `self`; otherwise it is `0`. The helper never recovers an ID
from a raw object pointer. Hash/equal stay Godot's default (`call_func` + userdata
pointer identity). The includer must declare `class_library` first.
- Object **values** in generated code are per-type fat pointers (`gdcc_<Type>_fat_ptr` from
module `object_fat_ptr_types.h`); `gdcc_helper.h` owns the shared raw/ID query and lifecycle
surface used by those helpers.
Expand Down
26 changes: 18 additions & 8 deletions doc/module_impl/frontend/diagnostic_manager.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@

## 文档状态

- 状态:事实源维护中(parser / skeleton / scope / variable / top-binding / chain-binding / expr-typing / type-check / loop-control / compile-check / exception 诊断链路已落地)
- 更新时间:2026-08-14
- 状态:事实源维护中(parser / skeleton / scope / variable / top-binding / chain-binding / expr-typing / type-check / loop-control / compile-check / exception 诊断链路已落地;已记录 lambda 的 compile gate 已解封
- 更新时间:2026-08-18
- 适用范围:
- `src/main/java/gd/script/gdcc/frontend/diagnostic/**`
- `src/main/java/gd/script/gdcc/frontend/parse/**`
Expand All @@ -17,6 +17,7 @@
- `doc/module_impl/frontend/scope_architecture_refactor_plan.md`
- `doc/module_impl/frontend/frontend_loop_control_flow_analyzer_implementation.md`
- `doc/module_impl/frontend/frontend_compile_check_analyzer_implementation.md`
- `doc/module_impl/frontend/frontend_lambda_implementation.md`
- `doc/analysis/frontend_semantic_analyzer_research_report.md`

---
Expand Down Expand Up @@ -130,6 +131,10 @@ frontend 当前已经冻结的诊断承载方式如下:
- `resolvedMembers`
- `resolvedCalls`
- `slotTypes`
- `forIterationPlans`
- `typeTestTargets`
- `containerLiteralPlans`
- `lambdaPlans`(nested resolve 入口经独立 `LAMBDA_RESOLUTION` owner 首次发布完整 plan,capture 声明处类型已填充;已 record lambda 的 `expressionTypes` 由 EXPR_TYPE owner 首次发布 `RESOLVED(GdCallableType)`;plan 携带 `returnType`——nested resolve 入口一次解析的声明返回类型,type-check return slot 与 lowering shell 共用)

其中:

Expand Down Expand Up @@ -211,20 +216,22 @@ deferred / unsupported diagnostics 一律通过 `DiagnosticManager` 发布。
其中 body/binding phase 新增 category 的语义固定为:

- `sema.variable_binding`
- variable analyzer 对 duplicate parameter、duplicate local、same-callable local shadowing、scope kind mismatch 发出的恢复性 source error
- variable analyzer 对 duplicate parameter、duplicate local、same-callable local shadowing、capture 与既有 callable slot 冲突(如 lambda 参数名为 `self` 时又需捕获 `self`)、scope kind mismatch 发出的恢复性 source error
- duplicate / shadowing local 的消息现在必须包含:当前声明位置、冲突声明位置、callable / block 归属、source path
- `sema.unsupported_parameter_default_value`
- variable analyzer 对 parameter default value 当前尚未接线时发出的 feature-boundary error
- `sema.unsupported_variable_inventory_subtree`
- variable analyzer 对 lambda / `match` / block-local `const` inventory 边界发出的 feature-boundary error
- variable analyzer 对 `match` / block-local `const` inventory 边界发出的 feature-boundary error
- lambda 已移出该边界:supported executable body 内的 lambda 会绑定 param / local / capture,不再发此诊断
- `sema.variable_slot_publication`
- var-type-post analyzer 对 supported callable-local `var` 因 earlier duplicate/shadowing reject 而无法发布 `slotTypes()` 时发出的 warning
- warning message 若能在当前 callable 边界内找到幸存的 accepted local / parameter / capture,必须带出该幸存绑定的语义类别与声明位置
- 该 warning 允许与 earlier `sema.variable_binding` 共存;compile-only gate 必须把“warning + 缺失 slot type”升级为 compile-blocking `sema.compile_check`
- `sema.binding`
- top binding 命中的 blocked / unknown / shadowing 诊断
- `sema.unsupported_binding_subtree`
- top binding 对 parameter default、lambda、`match`、block-local `const` 等明确 unsupported subtree 的边界 error
- top binding 对 parameter default、`match`、block-local `const` 等明确 unsupported subtree 的边界 error
- 已 `recordCallable` 的 lambda 改走 nested suite resolution,不再发此诊断;未记录的 lambda(property initializer 等)继续按此边界 fail-closed
- top binding 对 missing-scope / skipped subtree 的恢复诊断继续允许使用 warning
- `sema.member_resolution`
- chain binding 中 blocked / failed member step 的语义错误
Expand All @@ -242,6 +249,7 @@ deferred / unsupported diagnostics 一律通过 `DiagnosticManager` 发布。
- expr analyzer 对 assignment / subscript / generic deferred expression 等 expression-only deferred root 的 warning
- `sema.unsupported_expression_route`
- expr analyzer 对当前明确不支持的 direct-callable-invocation 等 expression route 的 error
- 已 `recordCallable` 的 lambda 不再发此诊断(表达式类型已转正为 `RESOLVED(GdCallableType)`);未记录的 lambda(property initializer / parameter default / skipped subtree)继续按此边界 fail-closed
- `sema.discarded_expression`
- expr analyzer 对 bare expression statement 中被丢弃的非 `void` 结果发出的 warning
- `sema.unsafe_call_argument`
Expand Down Expand Up @@ -276,13 +284,14 @@ deferred / unsupported diagnostics 一律通过 `DiagnosticManager` 发布。
- `sema.compile_check`
- compile-only `FrontendCompileCheckAnalyzer` 对进入 lowering 前仍不可编译的 surface 发出的最终 error
- 同时覆盖:
- 当前首批显式封口的 `assert`、`ConditionalExpression`、`PreloadExpression`、`GetNodeExpression`,以及按 route-aware policy 处理的 `ForStatement`;`ArrayExpression` / `DictionaryExpression`、`TypeTestExpression` 与 `CastExpression` 不属于显式封口列表
- 当前首批显式封口的 `assert`、`ConditionalExpression`、`PreloadExpression`、`GetNodeExpression`,以及按 route-aware policy 处理的 `ForStatement`;`ArrayExpression` / `DictionaryExpression`、`TypeTestExpression`、`CastExpression` 与已记录 `LambdaExpression` 不属于无条件显式封口列表
- compile surface 上 `expressionTypes()` / `resolvedMembers()` / `resolvedCalls()` 中仍残留的 `BLOCKED` / `DEFERRED` / `FAILED` / `UNSUPPORTED`
- feature-specific RESOLVED blocker:当前仅 Dictionary 实例 method-reference(`METHOD && BUILTIN && GdDictionaryType`)与 builtin type-meta static method-reference(`STATIC_METHOD && ownerKind == BUILTIN`)。signal 值读取、`.emit`、`.connect`/`.disconnect`、Object/self `METHOD`、非 Dictionary builtin 实例、GDCC/engine 静态与 bare utility 值读取已放行。bare blocker 按 published `symbolBindings().kind()` 定位,必须排除 `CallExpression.callee()`。详见 `frontend_signal_support.md` 与 `frontend_compile_check_analyzer_implementation.md` §4.2。
- supported callable-local `var` 因 `sema.variable_slot_publication` warning 仍缺失 `slotTypes()` 的 lowering-only fact 缺洞
- `assert` 在这里仍只是 compile-only blocked;共享 type-check 继续保留 Godot-compatible condition contract,不把它回退成 strict-bool `sema.type_check`
- `ForStatement` 已进入 shared semantic 并由 compile gate 按 route-aware policy 处理:读取 `forIterationPlans()` 与 `ForLoweringContractRegistry`,已注册 lowering contract 的 route 放行并进入 body 重扫 facts,未注册 contract 的 route(当前 `OBJECT_CUSTOM`)在 statement root 发 route-not-ready blocker(说明缺少 lowering route,而非 `FOR_SUBTREE` unsupported);已注册 route 的 CFG/body lowering 已落地
- 上述 3 类表达式(即 `ConditionalExpression`、`PreloadExpression`、`GetNodeExpression`,不含 statement 级 `assert` 与 route-aware 的 `ForStatement`;`ArrayExpression` / `DictionaryExpression`、`TypeTestExpression` 与 `CastExpression` 已完成 lowering/backend 闭环)属于 frontend 已识别但 lowering 尚未接通的 temporary compile intercept,不代表 parser / grammar / shared semantic 路径已经把它们判成不支持语法
- 已记录 `LambdaExpression`(published `FrontendLambdaPlan` + body)放上 compile surface 并递归扫描 body facts;未记录 lambda 保持 fail-closed,且不得在上游 unsupported owner 上重复包一层 `sema.compile_check`。合同见 `frontend_lambda_implementation.md`
- 上述 3 类表达式(即 `ConditionalExpression`、`PreloadExpression`、`GetNodeExpression`,不含 statement 级 `assert` 与 route-aware 的 `ForStatement`;`ArrayExpression` / `DictionaryExpression`、`TypeTestExpression`、`CastExpression` 与已记录 `LambdaExpression` 已完成 lowering/backend 闭环)属于 frontend 已识别但 lowering 尚未接通的 temporary compile intercept,不代表 parser / grammar / shared semantic 路径已经把它们判成不支持语法
- `ConditionalExpression` 当前单独被列入这份清单,是因为真正的 value-merge / branch-result materialization 尚未接通;compile gate 必须继续拦截。CFG 构建已由 `FrontendLoweringBuildCfgPass` 承接,不再依赖已移除的 metadata-only `FrontendLoweringCfgPass`
- `DYNAMIC` 不属于 compile blocker;它保留为 frontend 已接受的 runtime-open 事实,而不是 lowering 未实现状态
- 该 category 只属于 compile-only 入口,不属于默认共享语义 / inspection / 未来 LSP 入口
Expand Down Expand Up @@ -344,6 +353,7 @@ deferred / unsupported diagnostics 一律通过 `DiagnosticManager` 发布。
- `FrontendSemanticAnalyzer` 当前返回 `FrontendAnalysisData`
- analyze 流程围绕同一份共享分析数据推进
- interface/body suite resolver 路径会在每个 body statement boundary 刷新 `FrontendAnalysisData.diagnostics()`,让后一 statement 能读取 current-suite upstream diagnostic snapshot;suite export 在 patch transaction 应用后保留最终 body snapshot
- 已 `recordCallable` 的 lambda 由外层 statement 的 top-binding owner 触发 nested suite resolution:独立 `FrontendCallableExportBatch` 立即应用,`LAMBDA_RESOLUTION` owner patch 首次发布 `lambdaPlans`(capture 声明处类型),body 事实与普通 suite 走同一 statement boundary 诊断刷新;该 lambda 节点的 `expressionTypes` 由 EXPR_TYPE owner 首次发布 `RESOLVED(GdCallableType)`,silent 局部稳定化不解析 lambda initializer(slot 保持 inventory `Variant`)
- analyze 现在已经具备独立的多 phase 主链路:
- skeleton 结束后先发布 `updateModuleSkeleton(...)`
- 再发布一次 pre-scope `updateDiagnostics(...)`
Expand All @@ -356,7 +366,7 @@ deferred / unsupported diagnostics 一律通过 `DiagnosticManager` 发布。
- 调用 `FrontendVarTypePostAnalyzer.analyze(...)` 发布 callable-local `slotTypes()`
- 调用 `FrontendAnnotationUsageAnalyzer.analyze(...)` 对 retained annotation 的合法挂载位置发出 `sema.annotation_usage`
- 调用 `FrontendVirtualOverrideAnalyzer.analyze(...)` 对 engine virtual override 签名发出 `sema.virtual_override`
- 调用 `FrontendTypeCheckAnalyzer.analyze(...)` 对 ordinary local / class property / return typed contract 发出 `sema.type_check`,并对 property hint 发出 `sema.type_hint`
- 调用 `FrontendTypeCheckAnalyzer.analyze(...)` 对 ordinary local / class property / return typed contract 发出 `sema.type_check`,并对 property hint 发出 `sema.type_hint`;经 `scanNestedLambdaBodies` 显式 re-entry 遍历已 record lambda 的 body(plan 存在性为闸门,继承 enclosing callable 的 restriction/static context)
- 调用 `FrontendLoopControlFlowAnalyzer.analyze(...)` 对非法 `break` / `continue` 发出 `sema.loop_control_flow`
- 每个 phase 结束后都再次 `updateDiagnostics(...)`,把阶段边界快照刷新到最新 shared manager 状态
- `analyzeForCompile(...)` 在共享 11 phase 之后追加:
Expand Down
Loading