feat(minga-core): alpha-hashing per-language para Python, TS, JS, Go

Cierra el ultimo pendiente fundamentado del CHANGELOG. Cada lenguaje
soportado por minga tiene ahora su propio profile alpha-equivalente
— refactorings tipo "rename variable" no inflan el storage del repo
en ningun dialecto.

Refactor de alpha.rs (639 LOC) a modulo alpha/:
- alpha/common.rs: primitives compartidos (TAG_*, write_kind_and_field,
  emit_*, push_identifier_name). Garantiza wire bit-equivalente.
- alpha/rust.rs: logica Rust movida sin cambios funcionales.
- alpha/python.rs, alpha/ecmascript.rs, alpha/go.rs: nuevos.
- alpha/mod.rs: re-exporta hash_node_alpha (Rust legacy) + expone
  hash_alpha_with(dialect, node) que despacha al profile correcto.

Cobertura per-language:

Python: function_definition, lambda, for_statement, list/set/dict
comprehensions, generator_expression (con scope incremental:
binders del for_in_clause viven en clauses siguientes + body),
with_statement (recursando en as_pattern_target).

ECMAScript (TS+JS): function_declaration, function_expression,
method_definition, generator_function_*, arrow_function (paren y
shorthand), statement_block (con lexical_declaration y
variable_declaration introduciendo binders al resto), for_in_statement
(cubre for-of/for-in), for_statement (initializer C-style),
catch_clause, TS typed/optional parameters.

Go: function_declaration, method_declaration, func_literal (closure),
parameter_declaration con multi-name agrupados, block (con
short_var_declaration), for_statement con range_clause y for_clause,
if_statement con initializer.

Tests: 26 nuevos en alpha_polyglot.rs cubriendo rename invariants +
sanity negatives (function name matters, type matters, operation
matters) por cada lenguaje + cross-language sanity (mismo source en
distintos lenguajes -> hashes distintos).

141 tests verdes en minga-core (115 antes; +26 polyglot). 36 alpha
tests Rust intactos (sin regresion).

Pendientes Minga: minga-vfs (FUSE, proyecto independiente).
Cobertura adicional por-lenguaje (Python class, JS destructuring,
Go type_switch) queda como nice-to-have.
This commit is contained in:
Sergio
2026-05-09 19:06:48 +00:00
parent d1888e0901
commit 6be50c5b73
8 changed files with 1585 additions and 82 deletions
+90
View File
@@ -6,6 +6,96 @@ ratio/diff ver `git show <sha>`.
## 2026-05-09
### feat(minga-core): α-hashing per-language para Python, TypeScript, JavaScript, Go
Cierra el último pendiente fundamentado del CHANGELOG. Cada lenguaje
soportado por `minga` tiene ahora su propio profile α-equivalente —
dos versiones del mismo programa que difieren sólo en nombres de
variables ligadas producen el mismo hash, no importa el lenguaje.
Refactorings tipo "rename variable" no inflan el storage del repo
en ningún dialecto.
Refactor de `alpha.rs` (639 LOC) a módulo `alpha/`:
- **`alpha/common.rs`**: primitives compartidos (TAG_*, write_kind_and_field,
emit_leaf_marker, emit_binder_body, emit_identifier_ref, push_identifier_name).
Garantiza que el formato wire del hash sea bit-equivalente entre
todos los profiles.
- **`alpha/rust.rs`**: la lógica de Rust (movida desde alpha.rs sin
cambios funcionales).
- **`alpha/python.rs`**: nuevo.
- **`alpha/ecmascript.rs`**: nuevo (cubre TypeScript + JavaScript;
comparten la mayoría de los kinds).
- **`alpha/go.rs`**: nuevo.
- **`alpha/mod.rs`**: re-exporta `hash_node_alpha` (Rust legacy) +
expone `hash_alpha_with(dialect, node)` que despacha al profile
correspondiente.
Cobertura per-language:
**Python** (`def`, `lambda`, `for`, comprehensions, `with`):
- `function_definition` y `lambda`: parámetros (incluyendo
typed_parameter, default_parameter, *args, **kwargs) introducen
binders al body. El nombre de la función NO es α-anónimo.
- `for_statement`: el `left` (identifier o tuple) introduce
binder(es) al body.
- `list_comprehension`, `set_comprehension`, `dictionary_comprehension`,
`generator_expression`: cada `for_in_clause` añade binders que
viven en el body + clauses siguientes (semántica de scope
incremental de Python).
- `with_statement`: `as` introduce binder al body (recursando en
`as_pattern_target` para llegar al identifier).
**ECMAScript** (TS + JS):
- `function_declaration`, `function_expression`, `method_definition`,
`generator_function_*`: parameters → body. Soporta TS
`required_parameter` y `optional_parameter` (`x: number`,
`x?: number`).
- `arrow_function`: tanto `(x, y) => body` como shorthand `x => body`.
- `statement_block`: `lexical_declaration` (let/const) y
`variable_declaration` (var) introducen binders al resto del block.
- `for_in_statement` (cubre `for-of` y `for-in`): `left` → body.
- `for_statement` (C-style): initializer (lexical decl) introduce
binders al condition + increment + body.
- `catch_clause`: parameter → body.
**Go**:
- `function_declaration`, `method_declaration`, `func_literal` (closure):
`parameter_list` → body. `parameter_declaration` con varios names
agrupa varios binders bajo un mismo tipo (`a, b int`).
- `block`: `short_var_declaration` (`x := ...`) introduce binders
al resto.
- `for_statement` con `range_clause` (`for k, v := range m`): los
identifiers del `left` son binders al body.
- `for_statement` con `for_clause` (C-style): initializer → body.
- `if_statement` con `initializer` (`if x := init(); x > 0`):
binders viven en condition + consequence + alternative.
API:
- `hash_alpha_with(Dialect, &SemanticNode) -> ContentHash`
despacho per-dialect.
- `hash_node_alpha(&SemanticNode) -> ContentHash` — alias histórico
asume Rust (back-compat).
Tests: 26 nuevos en `tests/alpha_polyglot.rs`:
- Python (9): def rename, lambda rename, for-loop rename, list comp,
nested comp, with rename, function name matters, iterable name
matters, sanity negativo (operación distinta → hash distinto).
- JS/TS (9): function rename, function name matters, arrow rename,
arrow shorthand rename, let/const rename, for-of rename, classic
for rename, catch rename, TS typed param rename, TS type matters.
- Go (6): function rename, function name matters, short var decl
rename, range_clause rename, if-init rename, func_literal closure
rename.
- Cross-language (1): mismos shapes en lenguajes distintos
producen hashes distintos (sanity para evitar colisiones).
141 tests verdes en minga-core (115 antes; +26 polyglot). Refactor
sin regresión: 36 α-Rust tests siguen pasando.
Pendientes que quedan en Minga (orden de prioridad):
- `minga-vfs` FUSE (proyecto independiente, scope grande).
- Cobertura adicional por-lenguaje: Python class, JS destructuring,
Go type_switch, etc. — cada uno pequeño, no urgente.
### feat(minga-core): cierre del α-hashing de Rust — if let, while let, let-else, or-pattern, let-chains
Cierra los 5 pendientes documentados en `alpha.rs`. El hash
α-equivalente ahora es estable bajo renombre de TODOS los binders