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/CHANGELOG.md +15 -0
- package/README.md +159 -2
- package/dist/index.js +154 -0
- package/dist/index.js.map +30 -0
- package/dist/worker.js +153 -0
- package/dist/worker.js.map +25 -0
- package/docs/README.md +27 -0
- package/docs/arquitectura.md +174 -0
- package/docs/especificacion-v1.md +701 -0
- package/docs/guia-aprender-desde-el-codigo.md +91 -0
- package/docs/integracion.md +104 -0
- package/docs/lenguaje.md +537 -0
- package/docs/modo-mundo.md +128 -0
- package/docs/recetario.md +159 -0
- package/docs/repl.md +64 -0
- package/package.json +66 -4
- package/src/catalog.ts +256 -0
- package/src/challenge.ts +138 -0
- package/src/engine.ts +104 -0
- package/src/error-codes.ts +427 -0
- package/src/errors.ts +56 -0
- package/src/flow.ts +385 -0
- package/src/index.ts +81 -0
- package/src/printer.ts +133 -0
- package/src/runtime/builtins.ts +1426 -0
- package/src/runtime/compiler.ts +499 -0
- package/src/runtime/costs.ts +96 -0
- package/src/runtime/machine.ts +1521 -0
- package/src/runtime/prelude.ts +230 -0
- package/src/runtime/suggest.ts +33 -0
- package/src/runtime/values.ts +241 -0
- package/src/sandbox-host.ts +310 -0
- package/src/sandbox.ts +95 -0
- package/src/syntax/ast.ts +344 -0
- package/src/syntax/lexer.ts +266 -0
- package/src/syntax/parser.ts +1090 -0
- package/src/syntax/token.ts +215 -0
- package/src/worker.ts +18 -0
- package/src/world.ts +518 -0
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.
|