Skip to content

Publish immutable GML language-metadata API #861

Description

@Infiland

Parent: #817

Problem

The parser, emitter, source analysis, project collectors, and converter orchestration currently import underscore-prefixed language constants from gml_transpiler_parts/constants.py. This keeps the lexical/language-metadata boundary statically unenforceable, and many exported dictionaries are mutable at runtime.

This is the smallest coherent first slice of #817: language metadata is a leaf dependency for identifiers and tokens, and it can be made explicit without changing tokenization, preprocessing, parser behavior, or generated output.

Scope

  • Keep the supported repository-internal surface in src/conversion/gml_transpiler_parts/constants.py; do not add a wrapper that merely reimports private names and do not move the roughly 1,800-line registry table.
  • Publish non-underscore names for every constant currently imported across modules: precedence/operator metadata, identifier/literal/built-in sets, replacement tables, built-in variable metadata, virtual-key metadata, and every runtime-function category set.
  • Add one static literal __all__ containing exactly the 64 supported public names.
  • Annotate public values with Final and abstract collection types.
  • Back all mapping exports with types.MappingProxyType; make RIGHT_ASSOCIATIVE a frozenset. Existing tuple/scalar/frozenset values and frozen model instances remain immutable.
  • Preserve only _BUILTIN_VARIABLE_REGISTRY = BUILTIN_VARIABLE_REGISTRY as an unexported compatibility alias for the frozen top-level facade edge assigned to Slim the GML transpiler facade and enforce zero private phase imports #820.
  • Migrate imports/usages in api.py, emitter.py, enum_helpers.py, expression_parser.py, gml_function_dispatch.py, identifiers.py, source_map.py, statement_parser.py, statements.py, tokens.py, utils.py, objects.py, and script_generator.py.
  • Remove reportPrivateUsage=false only where this slice makes it unnecessary: all of gml_function_dispatch.py's directive and that field from identifiers.py, retaining its unused-symbol controls.

Acceptance criteria

  • constants.__all__ is a statically known exact 64-name, non-private surface.
  • No package or production module except the frozen top-level facade imports a private constant.
  • All mapping exports reject assignment/deletion, all set exports are frozen, and built-in registry values remain frozen BuiltinVariableMetadata.
  • The Inventory and freeze GML transpiler phase boundaries #815 architecture baseline changes exactly:
    • internal private edges: 209 -> 135;
    • production import edges: remain 60;
    • private production names: 22 -> 16;
    • private-usage suppressions: 17 -> 15.
  • The sole remaining private constants edge is the facade import of _BUILTIN_VARIABLE_REGISTRY, still assigned to Slim the GML transpiler facade and enforce zero private phase imports #820.
  • Preprocessed source, token kind/value/index/line/column, transpiled GDScript, source-map JSON, diagnostics, parser error locations, and golden outputs remain byte/value identical. No golden expectation update.
  • No top-level facade exports or signatures change.

Required verification

  • Run the focused Publish GML lexical and language-metadata phase APIs #817 tokenizer/transpiler/source-map/project collector suites and the golden/part-2 fixture suites.
  • Run ./venv/bin/pyright --warnings, the repository Ruff command, and the full unittest suite.
  • Run the exact Godot 4.7.2.stable.official.ed1daf0bf gates and pinned GameMaker LTS 2026 SNAP/Adding conversion gate.

Dependencies and order

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions