SYNX 3.8 es más rápido en todas partes, y todos los parsers por fin coinciden
SYNX 3.8.0 no cambia el lenguaje en absoluto. Lo que cambia es lo rápido que lo lee cada implementación, hasta 9,6 veces más rápido en TypeScript y de 2 a 3,6 veces en Rust, y que ahora todas dan la misma respuesta para el mismo archivo.
by APERTURESyndicate · 17 de octubre de 2026
Ya salió SYNX 3.8.0, y si lo único que haces es escribir archivos de configuración, no vas a ver nada nuevo en los archivos, porque la gramática no se ha movido ni un milímetro. Lo que se movió es todo lo que hay debajo: el núcleo en Rust, el paquete de TypeScript, los bindings de Python y Node y los siete ports nativos se midieron contra 3.7.4 en la misma máquina y con los mismos archivos, y luego se reconstruyeron justo donde se estaba yendo el tiempo.
Cuánto más rápido
La versión corta, escrita en el propio formato:
# 3.7.4 -> 3.8.0, same machine, same files
rust
config_2_5kb 38.6us -> 17.6us
static_4mb 60.1ms -> 35.3ms
active_1_2mb 81.0ms -> 22.5ms
typescript_node
config_2_5kb 34.0us -> 20.4us
active_1_2mb 297.5ms -> 31.1ms
python
config_2_5kb 50.3us -> 17.6us
synxl_100k 173.7ms -> 83.2msEl salto más grande está en TypeScript con documentos grandes que usan marcadores, y el motivo da un poco de vergüenza: cada clave :calc volvía a recorrer su expresión contra todas las demás claves del documento, así que el trabajo crecía con el cuadrado del tamaño del archivo. En Rust, casi toda la ganancia vino de la memoria. Con el asignador del sistema de Windows, un análisis normal pasaba casi la mitad del tiempo pidiendo memoria, y 3.8.0 la pide unas tres veces menos en archivos estáticos y unas cinco veces menos en modo activo. El formato binario .synxb recibió el mismo trato: las cadenas que más usa un documento ahora reciben los índices más cortos, así que los archivos son entre un 3 y un 20 % más pequeños en Rust y hasta un 40 % en TypeScript, y el mismo documento ahora siempre se compila en los mismos bytes, algo que 3.7.4 no garantizaba.
Los parsers en realidad no coincidían
Esto no lo estábamos buscando. Para asegurarnos de que el código más rápido daba los mismos resultados, empezamos a pasarle los mismos documentos generados al azar al núcleo en Rust y al paquete de TypeScript y a comparar lo que salía, y el 17 % de los documentos !active salieron distintos. A veces fallaba TypeScript, a veces Rust, y a veces Rust fallaba de forma distinta en cada ejecución: recorría los objetos en el orden de una tabla hash, así que el ejemplo tax:calc / total:calc sacado tal cual de la especificación fallaba con CALC_ERR más o menos en la mitad de las ejecuciones.
Y en cuanto empezamos a buscar, apareció más. Los marcadores dentro de los elementos de una lista nunca se aplicaban en Rust. Synx.stringify y .synxb cambiaban los datos a la vuelta: "007" volvía como el número 7, los bloques de código |+ perdían la sangría, y 1777 de 3000 documentos aleatorios no sobrevivían al viaje de ida y vuelta. Algunos documentos incluso podían tumbar el proceso entero: :clamp:nan:5 hacía que Rust entrara en pánico, y un archivo que se incluía a sí mismo desbordaba la pila. Los 55 están corregidos, y con el código final el núcleo en Rust y TypeScript coinciden en cada uno de los 70 000 documentos generados.
Siete ports, todos en 3.8.0
SYNX también tiene parsers nativos para Go, Java, .NET, Dart, C++, Swift y Godot, y se habían quedado unas cuantas versiones atrás. Ahora todos están en 3.8.0, comprobados del mismo modo contra el núcleo en Rust con miles de documentos generados cada uno, y no queda ninguna diferencia. Algunos cambiaron mucho más que otros: los ports de C++ y Swift tardaban 88 y 47 segundos con un documento activo de 1,2 MB y ahora tardan 33 y 95 milisegundos, y el addon de Godot ni siquiera compilaba en Godot 4.7 antes de esto.
Cómo actualizar
Tus archivos .synx no necesitan cambios. Los paquetes son @aperturesyndicate/synx-format en npm, synx-core en crates.io y synx-format en PyPI, y los ports llegan por sus registros de siempre. Si usas synx-core directamente desde Rust, los objetos ahora son un IndexMap ordenado en lugar de un HashMap, así que el código que construye su propio HashMap y lo envuelve necesita un .collect(), mientras que todo lo que lee con get e iteración compila igual que antes.
Hay una cosa que el formato todavía no puede expresar: una lista dentro de un elemento de lista, seguida de otro elemento, no sobrevive a escribirse y volver a leerse, porque SYNX mantiene una sola lista abierta a la vez. Eso está previsto para la 4.0, junto con las cadenas compactas, que en una copia de laboratorio del núcleo aceleraron el análisis otras 1,2 a 1,5 veces.
Todos los cambios, con las cifras, están en el registro de cambios y en la versión 3.8.0 en GitHub.



