codexivo 0.0.0-stage → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/docs/README.md ADDED
@@ -0,0 +1,27 @@
1
+ # Documentación de Codexivo
2
+
3
+ Bienvenido al compendio oficial del lenguaje **Codexivo**. Este directorio recopila guías para dos audiencias principales:
4
+
5
+ 1. **Personas que desean escribir programas en Codexivo** y necesitan una referencia clara de la sintaxis, los tipos y las herramientas disponibles.
6
+ 2. **Personas que quieren entender cómo está construido el intérprete** para poder extenderlo, depurarlo o utilizarlo como recurso educativo.
7
+
8
+ ## Guías disponibles
9
+
10
+ - [Especificación v1 (propuesta en revisión)](./especificacion-v1.md): el diseño objetivo del lenguaje por niveles, con las brechas frente a la implementación actual y las decisiones abiertas.
11
+ - [Especificación del lenguaje](./lenguaje.md): describe la sintaxis, palabras reservadas, tipos de dato y reglas semánticas que definen a Codexivo como si fuera un lenguaje formal.
12
+ - [Arquitectura del intérprete](./arquitectura.md): recorre el código fuente módulo por módulo para explicar cómo se procesa un programa desde el texto hasta su evaluación.
13
+ - [Guía práctica: entender el intérprete desde el código](./guia-aprender-desde-el-codigo.md): actividades guiadas para relacionar cada módulo con ejemplos reales del lenguaje.
14
+ - [Uso del REPL y flujo de trabajo](./repl.md): muestra cómo ejecutar el intérprete, guardar sesiones y aprovechar las herramientas de trazado en tiempo real.
15
+ - [Recetario de programas](./recetario.md): colección de ejemplos completos que ilustran patrones comunes de solución.
16
+ - [Integrar Codexivo en una página](./integracion.md): el worker del sandbox, su protocolo, el retroceso y los retos.
17
+ - [Modo mundo](./modo-mundo.md): el robot en la cuadrícula, el formato JSON de los mundos, sus eventos y los objetivos de un reto.
18
+
19
+ > ℹ️ Las guías están pensadas para leerse de forma progresiva. Si tu objetivo es aprender el lenguaje, comienza por la especificación y luego pon en práctica los ejemplos del recetario. Si deseas contribuir al código, revisa primero la arquitectura y después ejecuta los escenarios del REPL.
20
+
21
+ ## Convenciones
22
+
23
+ - Todo el contenido está en español y emplea la terminología oficial del proyecto ("procedimiento", "variable", etc.).
24
+ - Los bloques de código usan resaltado de sintaxis cuando aplica para facilitar la lectura comparando con JavaScript.
25
+ - Las referencias al código fuente incluyen rutas y nombres de clases/funciones exactas para que puedas ubicarlas rápidamente.
26
+
27
+ ¡Disfruta explorando Codexivo!
@@ -0,0 +1,174 @@
1
+ # Arquitectura del intérprete
2
+
3
+ Codexivo convierte texto en resultados en cuatro etapas. Cada una vive en su propio módulo y se puede usar por separado; eso es
4
+ lo que permite que el sandbox muestre los tokens, el árbol y la ejecución paso a paso del mismo programa.
5
+
6
+ ```
7
+ código ──tokenize──▶ tokens ──parse──▶ AST ──compile──▶ instrucciones ──Machine──▶ resultado, salida y eventos
8
+ ```
9
+
10
+ ## 1. Tokens y lexer (`src/syntax/token.ts`, `src/syntax/lexer.ts`)
11
+
12
+ `tokenize(código)` recorre el texto carácter por carácter y regresa `{ tokens, errors }`.
13
+
14
+ - Cada `Token` tiene su tipo, el texto exacto (`lexeme`), su valor ya interpretado (para números y textos) y su `span`: línea,
15
+ columna y desplazamiento de inicio y fin.
16
+ - Ignora espacios y comentarios (`//` y `/* */`).
17
+ - Nunca lanza una excepción: un carácter desconocido o un texto sin cerrar se reporta en `errors` y produce un token `ILLEGAL`
18
+ para que el parser pueda seguir.
19
+
20
+ ## 2. AST y parser (`src/syntax/ast.ts`, `src/syntax/parser.ts`)
21
+
22
+ `parse(código)` regresa `{ program, tokens, errors }`.
23
+
24
+ - El AST está hecho de **objetos planos** con un campo `kind`, un `id` único y su `span`. Se puede convertir a JSON o enviar a
25
+ un Web Worker sin perder nada. `walk` y `childrenOf` sirven para recorrerlo.
26
+ - El parser es de tipo Pratt: cada operador tiene una precedencia y el parser decide cómo agrupar comparando precedencias.
27
+ `y`/`o` tienen menos precedencia que las comparaciones, así que `1 < 2 y 5 < 4` se agrupa como `(1 < 2) y (5 < 4)`.
28
+ - `si … pero_si … si_no` se guarda como una lista de ramas en orden, no como `si` anidados.
29
+ - Ante un error, el parser lo registra, salta hasta un punto seguro (un `;`, una `}`, una palabra que empieza sentencia o una
30
+ línea nueva) y sigue. Así reporta varios errores en una pasada sin inventar errores en cascada.
31
+
32
+ ## 3. Compilador (`src/runtime/compiler.ts`)
33
+
34
+ `compile(program)` traduce el AST a una lista de instrucciones para una máquina de pila. Por ejemplo, `x += 1` se convierte en:
35
+
36
+ ```
37
+ step (inicio de la sentencia)
38
+ load x
39
+ const 1
40
+ binary +
41
+ store x
42
+ ```
43
+
44
+ Cada instrucción guarda el nodo del AST que la originó: así la máquina sabe qué parte del código está ejecutando, y los errores
45
+ y eventos apuntan al lugar exacto.
46
+
47
+ Las decisiones (`si`, `mientras`, `hasta_que`, `para`) se compilan como `branch`: sacan la condición de la pila, revisan que
48
+ sea lógica y saltan o no. `y`/`o` usan `shortCircuit` para no evaluar el lado derecho cuando no hace falta.
49
+
50
+ ## 4. Máquina (`src/runtime/machine.ts`)
51
+
52
+ `Machine` ejecuta las instrucciones con su **propia pila de valores y de llamadas**. Por eso:
53
+
54
+ - La recursión no depende de la pila de JavaScript: el límite lo pone la configuración (10 000 llamadas por defecto).
55
+ - Se puede **pausar** en cualquier momento y continuar después:
56
+ - `run(presupuesto)` ejecuta hasta terminar o hasta gastar cierto número de operaciones. Sirve para que un Web Worker ceda el
57
+ control y la página siga respondiendo.
58
+ - `step()` avanza hasta la siguiente sentencia o decisión.
59
+ - Con `breakpoints` (números de línea), `run()` se detiene antes de esas sentencias.
60
+ - Si `leer()` no tiene entrada y `interactiveInput` está activo, la máquina queda `esperando_entrada` hasta
61
+ `provideInput(línea)`.
62
+ - `snapshot()` regresa las llamadas activas con las variables de cada alcance, el contenido de las listas por referencia, el
63
+ nodo actual y la salida.
64
+ - Con `onEvent`, la máquina reporta lo que hace: `paso`, `declara`, `asigna` (con el valor anterior), `decide` (con la rama
65
+ tomada), `opera` (operandos y resultado), `llama`, `regresa`, `imprime`, `lee`, `error` y `fin`.
66
+ - Cuenta **operaciones** de forma determinista: el mismo programa con la misma entrada siempre da el mismo número.
67
+
68
+ Los valores (`src/runtime/values.ts`) son primitivos de JavaScript para números, textos, lógicos y `nulo`, y objetos con `id`
69
+ para listas y procedimientos. Los alcances (`Scope`) forman una cadena: cada bloque crea uno nuevo que apunta al de afuera.
70
+
71
+ ## 5. Biblioteca (`src/runtime/builtins.ts`, `prelude.ts`, `costs.ts`)
72
+
73
+ Cada procedimiento nativo declara cuántos argumentos acepta y recibe un contexto con lo que necesita de la máquina: escribir
74
+ salida, leer entrada, crear listas y diccionarios, números aleatorios con semilla y reportar errores ubicados en la llamada.
75
+ Todo nombre con acento se registra también sin él.
76
+
77
+ ### Procedimientos que reciben procedimientos
78
+
79
+ `mapear`, `filtrar`, `reducir`, `alguno`, `todos`, `buscar` y `ordenar` llaman a un procedimiento del programa. Un nativo de
80
+ JavaScript no puede hacerlo sin ejecutar la máquina dentro de sí misma, y eso rompería la pausa, el límite de llamadas, los
81
+ eventos y la cuenta de operaciones. Se consideraron tres caminos:
82
+
83
+ 1. **Escribirlos en Codexivo** y compilarlos una vez. ← _elegido_
84
+ 2. Instrucciones propias de la máquina (`map`, `filter`…) que empujan marcos sintéticos.
85
+ 3. Que un nativo regrese una "solicitud de llamada" y la máquina lo reanude.
86
+
87
+ `src/runtime/prelude.ts` contiene su código en Codexivo. Se compila al cargar el módulo con `compileProcedure(…, hidden)`, y
88
+ todas las máquinas comparten los procedimientos resultantes (son inmutables; sus `id` son negativos). Así, cuando `mapear`
89
+ llama a `f`, es una llamada normal de la máquina: `step()` se detiene dentro de `f`, cuenta para `maxCallDepth`, emite
90
+ `llama`/`regresa` y sus operaciones se cuentan.
91
+
92
+ Su propio código es **oculto** (`Chunk.hidden`):
93
+
94
+ - no es punto de pausa ni de interrupción y no cambia el nodo actual de `snapshot()`;
95
+ - no emite eventos, salvo `llama`/`regresa` de las llamadas hacia el programa, la salida, los errores y el fin;
96
+ - no cuenta instrucciones: la llamada se cobra según la tabla de costos;
97
+ - un error ahí se ubica en la llamada del programa (`mapear(…)`), y la pila muestra `programa > mapear > f`, sin los
98
+ procedimientos internos;
99
+ - en `snapshot()` aparece como un marco con `library: true` y sin variables.
100
+
101
+ Desde el código oculto se ven además unos nativos internos (`internals`: `revisar_lista`, `revisar_procedimiento`,
102
+ `revisar_logico`, `ordenar_natural`) que validan argumentos con los mismos mensajes que el resto de la biblioteca. El
103
+ programa no los ve. `ordenar` tiene su segundo parámetro opcional (`Chunk.minParams`).
104
+
105
+ ### Costo por operación
106
+
107
+ `src/runtime/costs.ts` es la única tabla de costos (§10 de la especificación): cada llamada a un procedimiento de la
108
+ biblioteca cuesta lo que dice la tabla (`n` para los que recorren su argumento, `n · ⌈log₂ n⌉` para `ordenar`) o 1 si no
109
+ aparece. Lo que hace `f` se cuenta aparte, como cualquier código del programa. Las llamadas que hace la biblioteca a sus
110
+ propios ayudantes no se cobran otra vez.
111
+
112
+ ## 6. Errores (`src/errors.ts`, `src/error-codes.ts`)
113
+
114
+ `CodexivoError` tiene `kind` (`léxico`, `sintaxis`, `ejecución` o `límite`), un `code` estable, `message`, `hint`, `span` y la
115
+ pila de llamadas. `formatError` lo convierte en el texto que muestran el REPL y la consola. `error-codes.ts` lista todos los
116
+ códigos con una explicación larga; una prueba revisa que no falte ni sobre ninguno.
117
+
118
+ ## Catálogo (`src/catalog.ts`)
119
+
120
+ `catalog` exporta como datos serializables lo que el sitio necesita para el resaltado, el autocompletado, la documentación y
121
+ los avisos del editor:
122
+
123
+ - `keywords`: las palabras reservadas por grupo (declaración, control, lógicas, literales, operadores), generadas desde
124
+ `KEYWORDS`;
125
+ - `operators`: símbolo, forma en palabras, precedencia, asociatividad y descripción;
126
+ - `library`: cada procedimiento con su nombre canónico y alias, nivel, categoría, firma, tipo que regresa, si cambia su
127
+ argumento, descripción y ejemplos ejecutables;
128
+ - `constants`, `errors` y `exampleWorld` (el mundo con el que corren los ejemplos del modo mundo).
129
+
130
+ La documentación de cada procedimiento vive junto a su definición: `define()` en `builtins.ts` la exige, y los
131
+ procedimientos de `prelude.ts` y del modo mundo tienen la suya al lado. Las pruebas ejecutan cada ejemplo del catálogo y
132
+ revisan que cada procedimiento registrado tenga entrada y viceversa. `bun run docs:biblioteca` genera las tablas de la
133
+ biblioteca en Markdown.
134
+
135
+ ## 7. API (`src/engine.ts`, `src/index.ts`)
136
+
137
+ - `run(código, opciones)` ejecuta un programa completo y regresa resultado, salida, errores, operaciones y, con `trace: true`,
138
+ los eventos.
139
+ - `prepare(código, opciones)` analiza el código y regresa una `Machine` lista para ejecutar paso a paso.
140
+ - `Session` comparte variables entre ejecuciones; la usa el REPL.
141
+
142
+ ## Diagrama de flujo (`src/flow.ts`, `src/printer.ts`)
143
+
144
+ `flowGraph(programa | procedimiento, opciones)` regresa un grafo serializable. La lógica que decide qué nodos y aristas
145
+ existen vive aquí, probada; el sitio solo calcula coordenadas (con ELK o dagre) y dibuja.
146
+
147
+ - **Nodos:** `inicio`, `fin`, `proceso`, `decisión` (`si`, `pero_si`, condiciones de bucles, `hasta_que`, `repetir`,
148
+ `para_cada`), `llamada`, `entrada` (`leer`), `salida` (`imprimir`) y `retorno`. Cada uno trae los `astIds` y `spans` de
149
+ los nodos del AST que representa, un texto corto (`suma += i`, `i <= 10`) y un `rank` sugerido: la distancia más larga
150
+ desde el inicio sin contar las vueltas.
151
+ - **Aristas:** `kind` (`normal`, `vuelta`, `romper`, `continuar`, `regresa`) y, al salir de una decisión, `label` (`sí`/`no`
152
+ en condiciones, `repetir`/`salir` en `repetir` y `para_cada`). Un `si` sin `si_no` lleva por el `no` a la sentencia
153
+ siguiente.
154
+ - **Opciones:** `group` junta sentencias simples consecutivas; `expandProcedures` agrega en `procedures` el grafo de cada
155
+ procedimiento con nombre y marca sus llamadas con `procedure`; `maxLabelLength` recorta las etiquetas.
156
+
157
+ **Resaltar el nodo activo:** cada `nodeId` de los eventos `paso` y `decide` (y el `ownerId` de `decide`) está en los
158
+ `astIds` de un nodo del grafo, así el sitio sabe qué nodo iluminar y, con el valor de la decisión, qué arista se tomó. Una
159
+ prueba lo comprueba ejecutando programas con cada estructura de control.
160
+
161
+ `printExpression` y `printStatement` convierten nodos del AST en texto de Codexivo con los paréntesis justos; sirven para
162
+ cualquier otra vista.
163
+
164
+ ## Sandbox en un Web Worker (`src/worker.ts`, `sandbox-host.ts`, `sandbox.ts`, `challenge.ts`)
165
+
166
+ `codexivo/worker` es el script del worker; `SandboxHost` tiene la lógica del protocolo sin depender de `postMessage`
167
+ (ejecución en tandas, eventos agrupados, retroceso por re-ejecución), y `createSandbox` es el cliente con promesas.
168
+ `evaluarReto` ejecuta los casos de un reto. Los detalles están en [`integracion.md`](./integracion.md).
169
+
170
+ ## Para estudiar el código
171
+
172
+ 1. `bun run repl` y escribe programas pequeños.
173
+ 2. Lee los tests de `tests/` en el orden del pipeline: `lexer`, `parser`, `machine`, `stepping`.
174
+ 3. Usa `tokenize`, `parse` y `run(código, { trace: true })` para ver cada etapa del mismo programa.