codexivo 0.2.0 → 1.0.0
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 +37 -1
- package/README.md +26 -25
- package/dist/index.js +153 -9
- package/dist/index.js.map +22 -12
- package/dist/worker.js +155 -0
- package/dist/worker.js.map +25 -0
- package/docs/README.md +2 -0
- package/docs/arquitectura.md +86 -4
- package/docs/especificacion-v1.md +211 -100
- package/docs/guia-aprender-desde-el-codigo.md +5 -5
- package/docs/integracion.md +104 -0
- package/docs/lenguaje.md +449 -60
- package/docs/modo-mundo.md +128 -0
- package/docs/recetario.md +63 -63
- package/package.json +11 -20
- package/src/catalog.ts +257 -0
- package/src/challenge.ts +138 -0
- package/src/engine.ts +7 -0
- package/src/error-codes.ts +432 -0
- package/src/flow.ts +385 -0
- package/src/index.ts +53 -1
- package/src/printer.ts +133 -0
- package/src/runtime/builtins.ts +1402 -65
- package/src/runtime/compiler.ts +278 -31
- package/src/runtime/costs.ts +96 -0
- package/src/runtime/machine.ts +722 -48
- package/src/runtime/prelude.ts +230 -0
- package/src/runtime/values.ts +120 -18
- package/src/sandbox-host.ts +310 -0
- package/src/sandbox.ts +95 -0
- package/src/syntax/ast.ts +120 -6
- package/src/syntax/lexer.ts +39 -5
- package/src/syntax/parser.ts +496 -72
- package/src/syntax/token.ts +49 -1
- package/src/worker.ts +18 -0
- package/src/world.ts +518 -0
- package/bin/codexivo.exe +0 -1
- package/postinstall.mjs +0 -38
|
@@ -6,12 +6,12 @@ antes la [arquitectura](./arquitectura.md).
|
|
|
6
6
|
## Programa semilla
|
|
7
7
|
|
|
8
8
|
```codexivo
|
|
9
|
-
variable saludo = "Codexivo"
|
|
9
|
+
variable saludo = "Codexivo"
|
|
10
10
|
variable arma_mensaje = procedimiento(nombre) {
|
|
11
|
-
variable prefijo = "Hola, "
|
|
12
|
-
regresa prefijo + nombre
|
|
13
|
-
}
|
|
14
|
-
arma_mensaje(saludo)
|
|
11
|
+
variable prefijo = "Hola, "
|
|
12
|
+
regresa prefijo + nombre
|
|
13
|
+
}
|
|
14
|
+
arma_mensaje(saludo)
|
|
15
15
|
```
|
|
16
16
|
|
|
17
17
|
Guárdalo en `semilla.cdx` y ejecútalo con `bun run src/cli.ts semilla.cdx`, o pégalo en el REPL.
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# Integrar Codexivo en una página
|
|
2
|
+
|
|
3
|
+
El sandbox ejecuta el código en un **Web Worker**, así un bucle infinito nunca congela la página. Este paquete trae el
|
|
4
|
+
worker (`codexivo/worker`) y un cliente tipado (`createSandbox`) para no reimplementar el protocolo en cada sitio.
|
|
5
|
+
|
|
6
|
+
## Ejemplo mínimo
|
|
7
|
+
|
|
8
|
+
```ts
|
|
9
|
+
import { createSandbox } from 'codexivo';
|
|
10
|
+
|
|
11
|
+
const worker = new Worker(new URL('codexivo/worker', import.meta.url), { type: 'module' });
|
|
12
|
+
const sandbox = createSandbox(worker);
|
|
13
|
+
|
|
14
|
+
const { errors } = await sandbox.load(código, { detail: 'decisiones' });
|
|
15
|
+
if (errors.length > 0) mostrarErrores(errors);
|
|
16
|
+
|
|
17
|
+
sandbox.onProgress(({ output }) => consola.append(output)); // cada tanda
|
|
18
|
+
const stopped = await sandbox.run();
|
|
19
|
+
consola.append(stopped.output);
|
|
20
|
+
|
|
21
|
+
if (stopped.status === 'esperando_entrada') {
|
|
22
|
+
await sandbox.provideInput(campo.value);
|
|
23
|
+
await sandbox.resume();
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Mensajes
|
|
28
|
+
|
|
29
|
+
`createSandbox` traduce cada método a un mensaje (`SandboxRequest`) y resuelve la promesa con la respuesta
|
|
30
|
+
(`SandboxResponse`). Quien quiera hablar con el worker directamente puede mandar los mensajes; todos llevan un `id`, y la
|
|
31
|
+
respuesta trae el mismo.
|
|
32
|
+
|
|
33
|
+
| Método | Mensaje | Responde con | Qué hace |
|
|
34
|
+
| ------------------------ | ------------------------ | ------------ | ------------------------------------------------------------------------- |
|
|
35
|
+
| `load(código, opciones)` | `cargar` | `cargado` | Tokens, AST, errores de sintaxis y la semilla de `aleatorio` |
|
|
36
|
+
| `run()` | `ejecutar` | `detenido` | Ejecuta hasta terminar, sin detenerse en los puntos de interrupción |
|
|
37
|
+
| `resume()` | `continuar` | `detenido` | Ejecuta hasta el siguiente punto de interrupción o hasta terminar |
|
|
38
|
+
| `step()` | `paso` | `detenido` | Avanza a la siguiente sentencia o decisión |
|
|
39
|
+
| `pause()` | `pausar` | `hecho` | La ejecución en curso se detiene al terminar la tanda (`reason: 'pausa'`) |
|
|
40
|
+
| `goToStep(n)` | `ir_a_paso` | `detenido` | Retrocede (o avanza) al paso `n` |
|
|
41
|
+
| `provideInput(línea)` | `entrada` | `hecho` | Da una línea a `leer()`; después hay que continuar |
|
|
42
|
+
| `closeInput()` | `cerrar_entrada` | `hecho` | Desde ahora `leer()` regresa `nulo` |
|
|
43
|
+
| `setBreakpoints(líneas)` | `puntos_de_interrupción` | `hecho` | Cambia los puntos de interrupción |
|
|
44
|
+
| `evaluarReto(código, r)` | `evaluar_reto` | `reto` | Evalúa un reto (ver abajo) |
|
|
45
|
+
|
|
46
|
+
Si una orden no se puede atender (no hay programa cargado, o la ejecución sigue en curso), la respuesta es `error` y la
|
|
47
|
+
promesa se rechaza.
|
|
48
|
+
|
|
49
|
+
`detenido` trae `status`, `reason` (`paso`, `punto_de_interrupción`, `pausa`, `entrada`, `fin`, `error` o `retroceso`),
|
|
50
|
+
`operations`, `steps`, la salida nueva, los eventos de la tanda, la fotografía (`snapshot`) y, según el caso, `result` o
|
|
51
|
+
`error`.
|
|
52
|
+
|
|
53
|
+
### Opciones de `cargar`
|
|
54
|
+
|
|
55
|
+
| Opción | Por defecto | Qué hace |
|
|
56
|
+
| -------------------------------------------- | -------------- | ------------------------------------------------------------------------------------------- |
|
|
57
|
+
| `input` | `[]` | Entrada inicial |
|
|
58
|
+
| `interactiveInput` | `true` | `leer()` sin entrada detiene la ejecución con `esperando_entrada` |
|
|
59
|
+
| `seed` | una al azar | Semilla de `aleatorio`; se conserva en los retrocesos |
|
|
60
|
+
| `maxOperations`, `maxCallDepth`, `maxOutput` | los de siempre | Límites |
|
|
61
|
+
| `breakpoints` | `[]` | Líneas donde se detiene `continuar` |
|
|
62
|
+
| `world` | — | Un mundo del [modo mundo](./modo-mundo.md), en JSON |
|
|
63
|
+
| `detail` | `decisiones` | Eventos por tanda: `nada`, `pasos` (`paso` y `robot`), `decisiones` (más `decide`) o `todo` |
|
|
64
|
+
| `batchSize` | 50 000 | Operaciones por tanda |
|
|
65
|
+
|
|
66
|
+
## Tandas
|
|
67
|
+
|
|
68
|
+
`run()` y `resume()` ejecutan en tandas de `batchSize` operaciones. Entre una y otra, el worker manda un `progreso`
|
|
69
|
+
(operaciones, pasos, salida nueva y eventos) y cede el control con `setTimeout(0)`; así puede recibir un `pausar`. Los
|
|
70
|
+
eventos llegan agrupados por tanda para no saturar `postMessage`.
|
|
71
|
+
|
|
72
|
+
## Retroceso
|
|
73
|
+
|
|
74
|
+
La máquina es determinista: el mismo programa con la misma entrada y la misma semilla da exactamente lo mismo. Por eso
|
|
75
|
+
retroceder no guarda estados: `goToStep(n)` vuelve a ejecutar desde el inicio, con la entrada que se ha dado y la misma
|
|
76
|
+
semilla, hasta el paso `n`, sin emitir los eventos intermedios. El `detenido` trae `replaceOutput: true` y toda la salida
|
|
77
|
+
hasta ese paso, y la fotografía es idéntica a la que había al pasar por ahí.
|
|
78
|
+
|
|
79
|
+
Un **paso** es un punto de pausa: cada `step()` avanza exactamente uno, y `steps` cuenta cuántos lleva la ejecución.
|
|
80
|
+
|
|
81
|
+
## Retos
|
|
82
|
+
|
|
83
|
+
`evaluarReto(código, reto)` ejecuta cada caso con su entrada y su límite de operaciones. Funciona en el worker y también
|
|
84
|
+
directamente en Bun (`import { evaluarReto } from 'codexivo'`), así los retos del sitio se prueban en CI.
|
|
85
|
+
|
|
86
|
+
```ts
|
|
87
|
+
// Estilo HackerRank: se compara lo que imprime.
|
|
88
|
+
evaluarReto(código, {
|
|
89
|
+
style: 'salida',
|
|
90
|
+
cases: [{ input: '3', expectedOutput: '9' }],
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// Estilo LeetCode: se llama a `resolver(…)` y se compara lo que regresa, por valor.
|
|
94
|
+
evaluarReto(código, {
|
|
95
|
+
style: 'regresa',
|
|
96
|
+
maxOperations: 100_000,
|
|
97
|
+
cases: [{ args: [[2, 7, 11, 15], 9], expected: [0, 1] }],
|
|
98
|
+
});
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Los argumentos y el valor esperado son JSON: los arreglos se vuelven listas y los objetos, diccionarios. En el estilo
|
|
102
|
+
`salida` se ignoran los espacios al final de cada línea y las líneas vacías del final, salvo con `exactOutput: true`. Cada
|
|
103
|
+
caso regresa si pasó, la salida, lo que regresó y lo esperado (como se escribirían en código), las operaciones y el error,
|
|
104
|
+
si hubo.
|