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
package/docs/README.md
CHANGED
|
@@ -13,6 +13,8 @@ Bienvenido al compendio oficial del lenguaje **Codexivo**. Este directorio recop
|
|
|
13
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
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
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.
|
|
16
18
|
|
|
17
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.
|
|
18
20
|
|
package/docs/arquitectura.md
CHANGED
|
@@ -68,15 +68,69 @@ sea lógica y saltan o no. `y`/`o` usan `shortCircuit` para no evaluar el lado d
|
|
|
68
68
|
Los valores (`src/runtime/values.ts`) son primitivos de JavaScript para números, textos, lógicos y `nulo`, y objetos con `id`
|
|
69
69
|
para listas y procedimientos. Los alcances (`Scope`) forman una cadena: cada bloque crea uno nuevo que apunta al de afuera.
|
|
70
70
|
|
|
71
|
-
## 5. Biblioteca (`src/runtime/builtins.ts`)
|
|
71
|
+
## 5. Biblioteca (`src/runtime/builtins.ts`, `prelude.ts`, `costs.ts`)
|
|
72
72
|
|
|
73
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 reportar errores ubicados en la llamada.
|
|
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.
|
|
75
76
|
|
|
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`)
|
|
77
113
|
|
|
78
114
|
`CodexivoError` tiene `kind` (`léxico`, `sintaxis`, `ejecución` o `límite`), un `code` estable, `message`, `hint`, `span` y la
|
|
79
|
-
pila de llamadas. `formatError` lo convierte en el texto que muestran el REPL y la consola.
|
|
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.
|
|
80
134
|
|
|
81
135
|
## 7. API (`src/engine.ts`, `src/index.ts`)
|
|
82
136
|
|
|
@@ -85,6 +139,34 @@ pila de llamadas. `formatError` lo convierte en el texto que muestran el REPL y
|
|
|
85
139
|
- `prepare(código, opciones)` analiza el código y regresa una `Machine` lista para ejecutar paso a paso.
|
|
86
140
|
- `Session` comparte variables entre ejecuciones; la usa el REPL.
|
|
87
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
|
+
|
|
88
170
|
## Para estudiar el código
|
|
89
171
|
|
|
90
172
|
1. `bun run repl` y escribe programas pequeños.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Codexivo v1 — Especificación del lenguaje
|
|
2
2
|
|
|
3
|
-
> **Estado:**
|
|
4
|
-
>
|
|
3
|
+
> **Estado:** implementada en la versión 1.0.0 (§16). Lo que funciona está en [`lenguaje.md`](./lenguaje.md), y todos sus
|
|
4
|
+
> ejemplos se prueban automáticamente.
|
|
5
5
|
>
|
|
6
6
|
> Las secciones marcadas con **✅ Decidido** fueron decisiones abiertas que ya se resolvieron.
|
|
7
7
|
|
|
@@ -24,6 +24,11 @@ Principios, en orden de prioridad cuando chocan:
|
|
|
24
24
|
5. **En el navegador y determinista.** Sin instalar nada. El mismo programa con la misma entrada
|
|
25
25
|
produce siempre el mismo resultado y la misma cantidad de operaciones.
|
|
26
26
|
|
|
27
|
+
> **✅ Decidido (#43) — regla de redacción.** Los ejemplos de nivel principiante no usan abreviaturas (`+=`, `++`) ni
|
|
28
|
+
> símbolos que tengan una alternativa en palabras, y no llevan `;` al final de línea. Las abreviaturas se presentan
|
|
29
|
+
> después, como atajos de algo que ya se entiende. Aplica al README, a `lenguaje.md`, al recetario, a la §9 y a los
|
|
30
|
+
> mensajes de error que sugieren código.
|
|
31
|
+
|
|
27
32
|
### Niveles
|
|
28
33
|
|
|
29
34
|
Cada característica pertenece a un nivel. Los niveles ordenan la documentación y los retos; no
|
|
@@ -38,26 +43,26 @@ bloquean nada en el editor.
|
|
|
38
43
|
## 1. Estado actual frente a v1
|
|
39
44
|
|
|
40
45
|
Probado contra `main` (`1ca0398`), cuyos 56 tests pasaban sin cubrir estos casos. La columna "Estado" dice qué ya resolvió
|
|
41
|
-
la reescritura del núcleo
|
|
42
|
-
|
|
43
|
-
| Caso | Antes | v1 | Estado
|
|
44
|
-
| -------------------------------- | ---------------------------------------------------------------------------------------------------- | ----------------------------------------- |
|
|
45
|
-
| `1 < 2 y 5 < 4` | Error. `y`/`o` tenían **más** precedencia que las comparaciones y se agrupaba como `1 < (2 y 5) < 4` | `falso` | ✅
|
|
46
|
-
| `no 1 == 2` | `falso` (se agrupaba como `(no 1) == 2`) | `verdadero` | ✅
|
|
47
|
-
| Varios `pero_si` seguidos | Solo se conservaba el último | Todas las ramas, en orden | ✅
|
|
48
|
-
| `procedimiento suma(a, b) { … }` | Error de sintaxis | Declaración con nombre |
|
|
49
|
-
| `// comentario` | Excepción de JavaScript (`value is null or undefined`) | Comentario | ✅
|
|
50
|
-
| `%`, `n++`, `n--` | Error de sintaxis | Soportados |
|
|
51
|
-
| `a[0] = 9` | Error de sintaxis | Asignación por índice |
|
|
52
|
-
| `nulo` | "identificador no encontrado" | Literal | ✅
|
|
53
|
-
| `imprimir(…)` / `leer()` | No existían; el programa solo devolvía su última expresión | Entrada y salida | ✅
|
|
54
|
-
| `1 / 0` | `Infinity` (el error `DIVISION_BY_ZERO` existía pero no se usaba) | Error | ✅
|
|
55
|
-
| `[1, 2] == [1, 2]` | `falso` | `verdadero` | ✅
|
|
56
|
-
| `mientras (verdadero) {}` | Bloqueaba el proceso | Error al superar el límite de operaciones | ✅
|
|
57
|
-
| `f(20000)` recursivo | `Maximum call stack size exceeded` | Funciona (límite configurable) | ✅
|
|
58
|
-
| `hasta_que` | Se tokenizaba como `WHILE` | Token propio `UNTIL` | ✅
|
|
59
|
-
| Mensajes de error | "en la linea" | "en la línea", con pista | ✅
|
|
60
|
-
| Docs y README | Usaban `sino`, `n++`, `%` y procedimientos con nombre que nunca funcionaron | Alineados con esta spec | ✅ (y se prueban)
|
|
46
|
+
la reescritura del núcleo y los pasos siguientes de §16.
|
|
47
|
+
|
|
48
|
+
| Caso | Antes | v1 | Estado |
|
|
49
|
+
| -------------------------------- | ---------------------------------------------------------------------------------------------------- | ----------------------------------------- | ----------------- |
|
|
50
|
+
| `1 < 2 y 5 < 4` | Error. `y`/`o` tenían **más** precedencia que las comparaciones y se agrupaba como `1 < (2 y 5) < 4` | `falso` | ✅ |
|
|
51
|
+
| `no 1 == 2` | `falso` (se agrupaba como `(no 1) == 2`) | `verdadero` | ✅ |
|
|
52
|
+
| Varios `pero_si` seguidos | Solo se conservaba el último | Todas las ramas, en orden | ✅ |
|
|
53
|
+
| `procedimiento suma(a, b) { … }` | Error de sintaxis | Declaración con nombre | ✅ (paso 5) |
|
|
54
|
+
| `// comentario` | Excepción de JavaScript (`value is null or undefined`) | Comentario | ✅ |
|
|
55
|
+
| `%`, `n++`, `n--` | Error de sintaxis | Soportados | ✅ (paso 4) |
|
|
56
|
+
| `a[0] = 9` | Error de sintaxis | Asignación por índice | ✅ (paso 5) |
|
|
57
|
+
| `nulo` | "identificador no encontrado" | Literal | ✅ |
|
|
58
|
+
| `imprimir(…)` / `leer()` | No existían; el programa solo devolvía su última expresión | Entrada y salida | ✅ |
|
|
59
|
+
| `1 / 0` | `Infinity` (el error `DIVISION_BY_ZERO` existía pero no se usaba) | Error | ✅ |
|
|
60
|
+
| `[1, 2] == [1, 2]` | `falso` | `verdadero` | ✅ |
|
|
61
|
+
| `mientras (verdadero) {}` | Bloqueaba el proceso | Error al superar el límite de operaciones | ✅ |
|
|
62
|
+
| `f(20000)` recursivo | `Maximum call stack size exceeded` | Funciona (límite configurable) | ✅ |
|
|
63
|
+
| `hasta_que` | Se tokenizaba como `WHILE` | Token propio `UNTIL` | ✅ |
|
|
64
|
+
| Mensajes de error | "en la linea" | "en la línea", con pista | ✅ |
|
|
65
|
+
| Docs y README | Usaban `sino`, `n++`, `%` y procedimientos con nombre que nunca funcionaron | Alineados con esta spec | ✅ (y se prueban) |
|
|
61
66
|
|
|
62
67
|
## 2. Léxico
|
|
63
68
|
|
|
@@ -82,29 +87,34 @@ variable canción_favorita = "Cielito lindo";
|
|
|
82
87
|
|
|
83
88
|
### 2.3 Literales
|
|
84
89
|
|
|
85
|
-
| Literal | Ejemplos | Notas
|
|
86
|
-
| ----------- | ------------------------------------- |
|
|
87
|
-
| Número | `10`, `3.14`, `.5`, `1_000_000` | Un solo tipo numérico (doble precisión). `_` solo
|
|
88
|
-
| Texto | `"hola"`, `'mundo'`, `"línea\nnueva"` | Escapes: `\n`, `\t`, `\"`, `\'`, `\\`
|
|
89
|
-
| Lógico | `verdadero`, `falso` |
|
|
90
|
-
| Nulo | `nulo` | Ausencia de valor
|
|
91
|
-
| Lista | `[1, 2, 3]`, `[]` |
|
|
92
|
-
| Diccionario | `{ "nombre": "Ana", "edad": 16 }` | Ver §4.6
|
|
90
|
+
| Literal | Ejemplos | Notas |
|
|
91
|
+
| ----------- | ------------------------------------- | ------------------------------------------------------------------- |
|
|
92
|
+
| Número | `10`, `3.14`, `.5`, `1_000_000` | Un solo tipo numérico (doble precisión). `_` solo entre dos dígitos |
|
|
93
|
+
| Texto | `"hola"`, `'mundo'`, `"línea\nnueva"` | Escapes: `\n`, `\t`, `\"`, `\'`, `\\` |
|
|
94
|
+
| Lógico | `verdadero`, `falso` | |
|
|
95
|
+
| Nulo | `nulo` | Ausencia de valor |
|
|
96
|
+
| Lista | `[1, 2, 3]`, `[]` | |
|
|
97
|
+
| Diccionario | `{ "nombre": "Ana", "edad": 16 }` | Ver §4.6 |
|
|
93
98
|
|
|
94
99
|
> **✅ Decidido — interpolación de texto.** ¿`"Hola, {nombre}"`? No en v1. `imprimir("Hola,", nombre)` resuelve el caso común sin agregar sintaxis
|
|
95
100
|
> dentro de las cadenas, y `texto(x)` cubre el resto.
|
|
96
101
|
|
|
97
102
|
### 2.4 Punto y coma
|
|
98
103
|
|
|
99
|
-
Separa sentencias.
|
|
100
|
-
|
|
104
|
+
Separa sentencias. Solo hace falta para poner dos en la misma línea; al final de línea es opcional y los ejemplos no lo
|
|
105
|
+
escriben (§0).
|
|
106
|
+
|
|
107
|
+
Sin `;`, un salto de línea termina la expresión: una línea que empieza con `-`, `(` o `[` es otra sentencia, no la
|
|
108
|
+
continuación de la anterior. Una expresión sigue en la línea siguiente solo si la línea termina en un operador
|
|
109
|
+
(`total = a +`) o si está dentro de paréntesis, corchetes o llaves. Así `x = 1` seguido de `-2` en la otra línea no se
|
|
110
|
+
convierte en silencio en `x = 1 - 2`.
|
|
101
111
|
|
|
102
112
|
### 2.5 Palabras reservadas
|
|
103
113
|
|
|
104
114
|
```
|
|
105
|
-
variable constante procedimiento regresa
|
|
115
|
+
variable constante procedimiento regresa dominio
|
|
106
116
|
si pero_si si_no
|
|
107
|
-
mientras hacer hasta_que para para_cada en repetir veces
|
|
117
|
+
mientras hacer hasta_que para desde hasta con_paso para_cada en repetir veces
|
|
108
118
|
romper continuar
|
|
109
119
|
verdadero falso nulo
|
|
110
120
|
y o no mod div
|
|
@@ -128,6 +138,7 @@ teclados lo facilitan. La documentación y los mensajes usan siempre la forma ca
|
|
|
128
138
|
| `"nulo"` | `nulo` |
|
|
129
139
|
| `"lista"` | `[1, "a", verdadero]` |
|
|
130
140
|
| `"diccionario"` | `{ "a": 1 }` |
|
|
141
|
+
| `"dominio"` | `dominio calculadora { … }` (§5.6) |
|
|
131
142
|
| `"procedimiento"` | Procedimientos del usuario y de la biblioteca |
|
|
132
143
|
|
|
133
144
|
- **Valor contra referencia.** Números, textos, lógicos y `nulo` se copian. Las listas y los
|
|
@@ -222,6 +233,10 @@ persona.ciudad = "León"; // agrega la clave
|
|
|
222
233
|
- Leer una clave que no existe es un error con la pista _"usa `tiene(d, clave)` para preguntar
|
|
223
234
|
antes"_.
|
|
224
235
|
- Al inicio de una sentencia, `{` abre un bloque; en cualquier otra posición, un diccionario.
|
|
236
|
+
- Las claves de un literal van entre comillas (`{ nombre: "Ana" }` es un error con pista); una clave calculada va
|
|
237
|
+
entre paréntesis: `{ (clave): valor }`. Una clave literal repetida es un error de sintaxis.
|
|
238
|
+
- `1` y `"1"` son claves distintas. `para_cada clave en d` recorre las claves; agregar o quitar claves durante el
|
|
239
|
+
recorrido es un error.
|
|
225
240
|
|
|
226
241
|
## 5. Sentencias
|
|
227
242
|
|
|
@@ -269,44 +284,83 @@ Las llaves son obligatorias.
|
|
|
269
284
|
|
|
270
285
|
### 5.4 Bucles
|
|
271
286
|
|
|
287
|
+
Una forma por intención:
|
|
288
|
+
|
|
289
|
+
| Intención | Forma | Nivel |
|
|
290
|
+
| --------------------------------------- | ---------------------------------------------- | ----- |
|
|
291
|
+
| Repetir n veces | `repetir n veces { }` | 🟢 |
|
|
292
|
+
| Contar | `para i desde a hasta b [con_paso p] { }` | 🟢 |
|
|
293
|
+
| Mientras se cumpla algo | `mientras (c) { }` / `hacer { } hasta_que (c)` | 🟢 |
|
|
294
|
+
| Recorrer una lista, texto o diccionario | `para_cada x en colección { }` | 🟡 |
|
|
295
|
+
| Puente hacia otros lenguajes | `para (inicio; condición; paso) { }` | 🔴 |
|
|
296
|
+
|
|
272
297
|
```codexivo
|
|
273
298
|
// 🟢 repite un número fijo de veces (herencia directa de Karel)
|
|
274
299
|
repetir 4 veces {
|
|
275
|
-
avanzar()
|
|
300
|
+
avanzar()
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// 🟢 cuenta, incluyendo los dos extremos
|
|
304
|
+
para i desde 1 hasta 10 {
|
|
305
|
+
suma = suma + i
|
|
306
|
+
}
|
|
307
|
+
para i desde 10 hasta 0 con_paso -2 {
|
|
308
|
+
imprimir(i)
|
|
276
309
|
}
|
|
277
310
|
|
|
278
311
|
// 🟢 mientras la condición sea verdadera
|
|
279
|
-
mientras (intentos
|
|
280
|
-
intentos
|
|
312
|
+
mientras (intentos es_menor_que 3) {
|
|
313
|
+
intentos = intentos + 1
|
|
281
314
|
}
|
|
282
315
|
|
|
283
316
|
// 🟢 al menos una vez, hasta que la condición sea verdadera
|
|
284
317
|
hacer {
|
|
285
|
-
número = leer_número()
|
|
286
|
-
} hasta_que (número
|
|
318
|
+
número = leer_número()
|
|
319
|
+
} hasta_que (número es_mayor_que 0)
|
|
287
320
|
|
|
288
|
-
// 🟡 recorrer una lista
|
|
321
|
+
// 🟡 recorrer una lista o un texto
|
|
289
322
|
para_cada fruta en ["mango", "piña"] {
|
|
290
|
-
imprimir(fruta)
|
|
291
|
-
}
|
|
292
|
-
para_cada i en rango(1, 10) {
|
|
293
|
-
imprimir(i);
|
|
323
|
+
imprimir(fruta)
|
|
294
324
|
}
|
|
295
325
|
|
|
296
326
|
// 🟡 recorrer un diccionario
|
|
297
327
|
para_cada clave, valor en persona {
|
|
298
|
-
imprimir(clave, valor)
|
|
328
|
+
imprimir(clave, valor)
|
|
299
329
|
}
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
> **✅ Decidido (#43) — `para … desde … hasta` es el `para` principal.** «Para i desde 1 hasta 10» es lo que la persona
|
|
333
|
+
> quiere decir; el `for` de C tiene tres partes separadas por `;` que no dicen qué son. `con_paso` lleva guion bajo para no
|
|
334
|
+
> reservar `paso`, que es un nombre común. `hasta` y `hasta_que` son palabras distintas. Después de `para`, un `(` empieza
|
|
335
|
+
> la forma clásica y un nombre, esta.
|
|
336
|
+
|
|
337
|
+
- **`para i desde a hasta b con_paso p`:**
|
|
338
|
+
- `i` se declara sola, sin `variable`, es nueva en cada vuelta y solo existe dentro del cuerpo. Cambiarla dentro del
|
|
339
|
+
bucle es el error `VARIABLE_DE_PARA` («la variable de un `para` avanza sola»).
|
|
340
|
+
- Incluye los dos extremos. El paso por defecto es `1`.
|
|
341
|
+
- `desde`, `hasta` y `con_paso` se evalúan **una vez**, al empezar; cambiar después la variable usada en `hasta` no
|
|
342
|
+
afecta al bucle.
|
|
343
|
+
- Sin magia: `desde` mayor que `hasta` sin `con_paso` es un error con la pista _«para contar hacia atrás escribe
|
|
344
|
+
`con_paso -1`»_ (no se invierte solo ni hace cero vueltas en silencio). Un paso en el sentido contrario también
|
|
345
|
+
(`PARA_SENTIDO_CONTRARIO`), igual que `con_paso 0` (`PARA_PASO_CERO`) o límites que no son números
|
|
346
|
+
(`PARA_LÍMITE_INVÁLIDO`).
|
|
347
|
+
- Cada vuelta emite `decide` con `label: 'para'` y `declara` con el nuevo valor de `i`.
|
|
348
|
+
- `para_cada i en rango(1, 10)` deja de ser la forma recomendada para contar; `rango()` sigue creando listas.
|
|
349
|
+
- `romper` sale del bucle más cercano; `continuar` salta a la siguiente vuelta. Fuera de un bucle son un error de
|
|
350
|
+
sintaxis, también dentro de un procedimiento: no cruzan el límite de una llamada.
|
|
351
|
+
- `repetir n veces` exige un número entero no negativo.
|
|
352
|
+
- Modificar la longitud de una lista mientras se recorre con `para_cada` es un error.
|
|
300
353
|
|
|
301
|
-
|
|
354
|
+
**🔴 Puente hacia otros lenguajes.** El `para` clásico se conserva para practicar antes de pasar a C, Java o JavaScript:
|
|
355
|
+
|
|
356
|
+
```codexivo
|
|
302
357
|
para (variable i = 0; i < 10; i++) {
|
|
303
|
-
imprimir(i)
|
|
358
|
+
imprimir(i)
|
|
304
359
|
}
|
|
305
360
|
```
|
|
306
361
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
- Modificar la longitud de una lista mientras se recorre con `para_cada` es un error.
|
|
362
|
+
Es `para i desde 0 hasta 9` escrito a mano: la condición se vuelve a evaluar en cada vuelta y la variable se puede cambiar
|
|
363
|
+
dentro del cuerpo. La documentación lo presenta en su propia sección, comparándolo con `para … desde … hasta`.
|
|
310
364
|
|
|
311
365
|
### 5.5 Procedimientos
|
|
312
366
|
|
|
@@ -322,7 +376,7 @@ mapear([1, 2, 3], doble); // [2, 4, 6]
|
|
|
322
376
|
```
|
|
323
377
|
|
|
324
378
|
- Las declaraciones con nombre se pueden usar antes de aparecer en su bloque; eso permite la
|
|
325
|
-
recursión mutua.
|
|
379
|
+
recursión mutua. Por eso su nombre no se puede repetir en el bloque, ni con otro procedimiento ni con una variable.
|
|
326
380
|
- Llamar con un número distinto de argumentos es un error. Hoy los faltantes se rellenan con `nulo`;
|
|
327
381
|
en v1 no.
|
|
328
382
|
- `regresa` sin valor regresa `nulo`, y un procedimiento que termina sin `regresa` también regresa `nulo`.
|
|
@@ -330,6 +384,36 @@ mapear([1, 2, 3], doble); // [2, 4, 6]
|
|
|
330
384
|
- Los procedimientos capturan las variables de donde se crearon (closures).
|
|
331
385
|
- La profundidad de recursión solo la limita la configuración (por defecto 10 000), no JavaScript.
|
|
332
386
|
|
|
387
|
+
### 5.6 Dominios
|
|
388
|
+
|
|
389
|
+
> **✅ Decidido (#19) — `dominio` es un espacio de nombres**, no un objeto ni un módulo. Agrupa declaraciones bajo un
|
|
390
|
+
> nombre; no hay `importar` ni archivos.
|
|
391
|
+
|
|
392
|
+
```codexivo
|
|
393
|
+
dominio calculadora {
|
|
394
|
+
variable operaciones = 0;
|
|
395
|
+
procedimiento suma(a, b) {
|
|
396
|
+
operaciones++;
|
|
397
|
+
regresa a + b;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
calculadora.suma(1, 3); // 4
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
- **Contenido:** solo declaraciones (`variable`, `constante`, `procedimiento` y otros `dominio`). Cualquier otra
|
|
404
|
+
sentencia es el error de sintaxis `DOMINIO_SOLO_DECLARACIONES`. Las declaraciones se ejecutan en orden al llegar al
|
|
405
|
+
dominio, y los procedimientos con nombre existen desde el inicio, como en cualquier bloque.
|
|
406
|
+
- **Alcance:** dentro del dominio sus miembros se usan sin prefijo y se ve lo que está fuera. Fuera se usan con `.`
|
|
407
|
+
(`geometría.círculo.área(1)`); con `[ ]` es un error. Un miembro que no existe es `MIEMBRO_INEXISTENTE`, con
|
|
408
|
+
sugerencia si se parece a otro.
|
|
409
|
+
- **Asignar desde fuera:** solo a los miembros declarados con `variable`. Las constantes, los procedimientos y los
|
|
410
|
+
dominios internos son `MIEMBRO_DE_SOLO_LECTURA`, y agregar un miembro nuevo es `MIEMBRO_INEXISTENTE`: así
|
|
411
|
+
`calculadora.suma` siempre es el mismo procedimiento.
|
|
412
|
+
- **Anidados:** un dominio puede contener otros.
|
|
413
|
+
- **Valor:** el nombre del dominio es constante. El dominio es un valor de tipo `"dominio"` con referencia: el sandbox
|
|
414
|
+
lo muestra en la memoria con sus miembros (`snapshot().heap`), y cambiar un miembro emite `asigna` con su ruta
|
|
415
|
+
(`calculadora.operaciones`). No es un diccionario: no se recorre con `para_cada` ni tiene `longitud`.
|
|
416
|
+
|
|
333
417
|
## 6. Entrada y salida
|
|
334
418
|
|
|
335
419
|
| Procedimiento | Qué hace |
|
|
@@ -345,24 +429,26 @@ mapear([1, 2, 3], doble); // [2, 4, 6]
|
|
|
345
429
|
|
|
346
430
|
## 7. Errores
|
|
347
431
|
|
|
348
|
-
Cada error es un objeto, no solo un texto
|
|
432
|
+
Cada error es un objeto, no solo un texto. Los campos de la API van en inglés, como el resto (`kind`, `span`); todo lo que
|
|
433
|
+
lee quien aprende va en español:
|
|
349
434
|
|
|
350
435
|
```ts
|
|
351
436
|
{
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
pila: ["programa", "promedio(lista)"]
|
|
437
|
+
kind: "léxico" | "sintaxis" | "ejecución" | "límite",
|
|
438
|
+
code: "DIVISIÓN_ENTRE_CERO",
|
|
439
|
+
message: "No se puede dividir entre cero.",
|
|
440
|
+
hint: "Revisa que `divisor` no valga 0 antes de dividir.",
|
|
441
|
+
span: { start: { line: 4, column: 12, offset: 80 }, end: { line: 4, column: 23, offset: 91 } },
|
|
442
|
+
callStack: ["programa", "promedio"]
|
|
359
443
|
}
|
|
360
444
|
```
|
|
361
445
|
|
|
446
|
+
Cada `code` tiene una explicación larga en el catálogo (`catalog.errors`).
|
|
447
|
+
|
|
362
448
|
- Los mensajes dicen **qué pasó** y la pista **qué revisar**, en español correcto y con acentos.
|
|
363
449
|
- El parser se recupera y reporta varios errores, pero el sandbox destaca el primero.
|
|
364
|
-
- `afirmar(condición, mensaje)` detiene el programa si la condición es falsa
|
|
365
|
-
directa para practicar verificación.
|
|
450
|
+
- `afirmar(condición, mensaje)` detiene el programa con `AFIRMACIÓN_FALLIDA` si la condición es falsa; el mensaje
|
|
451
|
+
es opcional. Es la herramienta más directa para practicar verificación.
|
|
366
452
|
- Sin `intentar`/`capturar` en v1: un error detiene el programa, y eso es lo que queremos que se vea.
|
|
367
453
|
|
|
368
454
|
## 8. Biblioteca estándar
|
|
@@ -394,6 +480,10 @@ cambian la lista; todo lo demás regresa un valor nuevo.**
|
|
|
394
480
|
`reemplazar(t, buscar, poner)`, `contiene`, `empieza_con`, `termina_con`, `posición_de` (regresa `-1`
|
|
395
481
|
si no está), `subtexto(t, inicio, fin)`, `caracteres(t)`, `código_de(c)`, `carácter_de(n)`.
|
|
396
482
|
|
|
483
|
+
> **✅ Decidido — `subtexto` y `rebanar` no incluyen el fin.** `subtexto("hola", 1, 3)` es `"ol"`. Así
|
|
484
|
+
> `fin - inicio` es la cantidad de elementos y `rebanar(l, 0, longitud(l))` es la lista completa. `rango`, que
|
|
485
|
+
> enumera, sí incluye el final; estos dos, que cortan, no.
|
|
486
|
+
|
|
397
487
|
### 🟡 Listas
|
|
398
488
|
|
|
399
489
|
| Nombre | Descripción |
|
|
@@ -417,7 +507,14 @@ inserción.
|
|
|
417
507
|
### 🔴 Procedimientos como valores
|
|
418
508
|
|
|
419
509
|
`mapear(l, f)`, `filtrar(l, f)`, `reducir(l, f, inicial)`, `alguno(l, f)`, `todos(l, f)`,
|
|
420
|
-
`buscar(l, f)` (el primero que cumple, o `nulo`)
|
|
510
|
+
`buscar(l, f)` (el primero que cumple, o `nulo`), `ordenar(l, va_antes)`.
|
|
511
|
+
|
|
512
|
+
> **✅ Decidido — el comparador de `ordenar` regresa un lógico.** `va_antes(a, b)` responde «¿va `a` antes que `b`?»
|
|
513
|
+
> (`procedimiento(a, b) { regresa a < b; }`). Es la pregunta que uno se hace al ordenar a mano, no exige entender el
|
|
514
|
+
> signo de una resta, y un número es un error. El orden es estable.
|
|
515
|
+
>
|
|
516
|
+
> Se implementan en Codexivo (ver `docs/arquitectura.md`), así una llamada a `f` se pausa, se traza y cuenta
|
|
517
|
+
> operaciones como cualquier otra.
|
|
421
518
|
|
|
422
519
|
### 🔴 Estructuras de datos
|
|
423
520
|
|
|
@@ -437,15 +534,15 @@ diccionarios y `.`.
|
|
|
437
534
|
|
|
438
535
|
```codexivo
|
|
439
536
|
// 🟢 FizzBuzz
|
|
440
|
-
|
|
441
|
-
si (n mod 15
|
|
442
|
-
imprimir("FizzBuzz")
|
|
443
|
-
} pero_si (n mod 3
|
|
444
|
-
imprimir("Fizz")
|
|
445
|
-
} pero_si (n mod 5
|
|
446
|
-
imprimir("Buzz")
|
|
537
|
+
para n desde 1 hasta 15 {
|
|
538
|
+
si (n mod 15 es_igual_a 0) {
|
|
539
|
+
imprimir("FizzBuzz")
|
|
540
|
+
} pero_si (n mod 3 es_igual_a 0) {
|
|
541
|
+
imprimir("Fizz")
|
|
542
|
+
} pero_si (n mod 5 es_igual_a 0) {
|
|
543
|
+
imprimir("Buzz")
|
|
447
544
|
} si_no {
|
|
448
|
-
imprimir(n)
|
|
545
|
+
imprimir(n)
|
|
449
546
|
}
|
|
450
547
|
}
|
|
451
548
|
```
|
|
@@ -453,42 +550,42 @@ para_cada n en rango(1, 15) {
|
|
|
453
550
|
```codexivo
|
|
454
551
|
// 🟡 Búsqueda binaria
|
|
455
552
|
procedimiento buscar_binaria(lista, objetivo) {
|
|
456
|
-
variable inicio = 0
|
|
457
|
-
variable fin = longitud(lista) - 1
|
|
458
|
-
mientras (inicio
|
|
459
|
-
variable medio = (inicio + fin) div 2
|
|
553
|
+
variable inicio = 0
|
|
554
|
+
variable fin = longitud(lista) - 1
|
|
555
|
+
mientras (inicio es_menor_o_igual_a fin) {
|
|
556
|
+
variable medio = (inicio + fin) div 2
|
|
460
557
|
si (lista[medio] es_igual_a objetivo) {
|
|
461
|
-
regresa medio
|
|
558
|
+
regresa medio
|
|
462
559
|
} pero_si (lista[medio] es_menor_que objetivo) {
|
|
463
|
-
inicio = medio + 1
|
|
560
|
+
inicio = medio + 1
|
|
464
561
|
} si_no {
|
|
465
|
-
fin = medio - 1
|
|
562
|
+
fin = medio - 1
|
|
466
563
|
}
|
|
467
564
|
}
|
|
468
|
-
regresa -1
|
|
565
|
+
regresa -1
|
|
469
566
|
}
|
|
470
567
|
```
|
|
471
568
|
|
|
472
569
|
```codexivo
|
|
473
570
|
// 🔴 Recorrido en anchura: distancia mínima en un grafo
|
|
474
571
|
procedimiento distancia(grafo, origen, destino) {
|
|
475
|
-
variable visitados = { }
|
|
476
|
-
variable cola = [[origen, 0]]
|
|
477
|
-
visitados[origen] = verdadero
|
|
572
|
+
variable visitados = { }
|
|
573
|
+
variable cola = [[origen, 0]]
|
|
574
|
+
visitados[origen] = verdadero
|
|
478
575
|
|
|
479
576
|
mientras (longitud(cola) > 0) {
|
|
480
|
-
variable actual = desencolar(cola)
|
|
577
|
+
variable actual = desencolar(cola)
|
|
481
578
|
si (actual[0] == destino) {
|
|
482
|
-
regresa actual[1]
|
|
579
|
+
regresa actual[1]
|
|
483
580
|
}
|
|
484
581
|
para_cada vecino en grafo[actual[0]] {
|
|
485
582
|
si (no tiene(visitados, vecino)) {
|
|
486
|
-
visitados[vecino] = verdadero
|
|
487
|
-
encolar(cola, [vecino, actual[1] + 1])
|
|
583
|
+
visitados[vecino] = verdadero
|
|
584
|
+
encolar(cola, [vecino, actual[1] + 1])
|
|
488
585
|
}
|
|
489
586
|
}
|
|
490
587
|
}
|
|
491
|
-
regresa -1
|
|
588
|
+
regresa -1
|
|
492
589
|
}
|
|
493
590
|
```
|
|
494
591
|
|
|
@@ -497,7 +594,7 @@ procedimiento distancia(grafo, origen, destino) {
|
|
|
497
594
|
- **Operaciones.** Cada operación básica (leer una variable, poner un valor, sumar, comparar, asignar, decidir, llamar)
|
|
498
595
|
cuenta como una. Los procedimientos de la biblioteca
|
|
499
596
|
cuentan según el trabajo que hacen (por ejemplo, `ordenar` sobre `n` elementos cuesta
|
|
500
|
-
`n · log₂ n`). La misma ejecución da siempre el mismo número, y los retos lo usan en lugar del
|
|
597
|
+
`n · ⌈log₂ n⌉`, y `contiene` cuesta `n`). La tabla vive en `src/runtime/costs.ts` y se documenta en `lenguaje.md`. La misma ejecución da siempre el mismo número, y los retos lo usan en lugar del
|
|
501
598
|
tiempo.
|
|
502
599
|
- **Límites configurables** con valores por defecto: operaciones (10 millones en el sandbox; cada
|
|
503
600
|
reto define el suyo), profundidad de recursión (10 000) y tamaño de la salida (1 MB). Superarlos es
|
|
@@ -517,12 +614,14 @@ Es lo que necesitan el sandbox, los diagramas, la máquina de estados y el modo
|
|
|
517
614
|
- Cada nodo del AST tiene un identificador estable y su **rango** en el código (inicio y fin, en
|
|
518
615
|
línea, columna y desplazamiento).
|
|
519
616
|
- Cada token conserva su rango, para la vista de tokens.
|
|
520
|
-
- La máquina emite eventos: `paso` (inicio de una sentencia), `declara`, `asigna` (antes/después),
|
|
617
|
+
- La máquina emite eventos: `paso` (inicio de una sentencia), `declara`, `asigna` (antes/después), `modifica` (un
|
|
618
|
+
elemento de una lista o diccionario, con su `ref`, la clave y el valor antes/después),
|
|
521
619
|
`decide` (condición, valor y rama tomada), `opera` (operandos y resultado), `llama`/`regresa`,
|
|
522
620
|
`imprime`/`lee`, `error` y `fin`. Cada uno lleva el número de operaciones y la profundidad de llamadas.
|
|
523
621
|
- En cualquier pausa se puede pedir una fotografía (`snapshot`) con las llamadas activas y las variables de
|
|
524
622
|
cada alcance. Listas y diccionarios tienen un identificador de referencia, para dibujar cuándo dos
|
|
525
|
-
variables comparten el mismo valor.
|
|
623
|
+
variables comparten el mismo valor. `heap` guarda, por referencia, los elementos de cada lista y los pares
|
|
624
|
+
`{ key, value }` de cada diccionario.
|
|
526
625
|
- El diagrama de flujo se genera desde el AST; la máquina de estados se anima desde los eventos.
|
|
527
626
|
Ninguno de los dos inventa información que el intérprete no produjo.
|
|
528
627
|
|
|
@@ -539,26 +638,35 @@ existen cuando el programa corre en un mundo.
|
|
|
539
638
|
| `dejar_zumbador()` | `mirando_al_norte()`, `mirando_al_sur()`, `mirando_al_este()`, `mirando_al_oeste()` |
|
|
540
639
|
| `apagar()` | |
|
|
541
640
|
|
|
542
|
-
Chocar con una pared
|
|
543
|
-
|
|
544
|
-
|
|
641
|
+
Chocar con una pared (`CHOQUE_CON_PARED`), recoger donde no hay zumbadores (`SIN_ZUMBADORES`), dejar sin tener
|
|
642
|
+
(`MOCHILA_VACÍA`) o hacer cualquier acción después de `apagar()` (`ROBOT_APAGADO`) es un error de ejecución, con la
|
|
643
|
+
posición y la orientación del robot. `apagar()` no termina el programa; las preguntas siguen funcionando. No hay
|
|
644
|
+
`girar_derecha()`: construirlo con tres `girar_izquierda()` es el primer ejercicio, igual que en Karel.
|
|
645
|
+
|
|
646
|
+
El formato del mundo (versión 1), los eventos `robot` y los objetivos de un reto están en
|
|
647
|
+
[`modo-mundo.md`](./modo-mundo.md).
|
|
545
648
|
|
|
546
649
|
## 13. Fuera de v1
|
|
547
650
|
|
|
548
651
|
Módulos e `importar`, clases y métodos, `intentar`/`capturar`, asincronía, archivos, red, tipos
|
|
549
652
|
estáticos y `según`/`caso`. Se pueden reconsiderar después, siempre con el principio 1 como filtro.
|
|
550
653
|
|
|
654
|
+
`dominio` (§5.6) no es un módulo: agrupa nombres dentro del mismo programa, sin archivos ni `importar`.
|
|
655
|
+
|
|
551
656
|
## 14. Cambios que rompen programas existentes
|
|
552
657
|
|
|
553
658
|
Codexivo no tiene usuarios todavía, así que v1 se permite romper compatibilidad:
|
|
554
659
|
|
|
555
|
-
- condiciones estrictas (
|
|
660
|
+
- condiciones estrictas (§4.5);
|
|
556
661
|
- error al llamar con un número distinto de argumentos;
|
|
557
662
|
- error al redeclarar o al asignar sin declarar;
|
|
558
663
|
- `agregar` pasa a modificar la lista (antes regresaba una nueva);
|
|
559
664
|
- un procedimiento sin `regresa` regresa `nulo` (antes regresaba el valor de su última expresión);
|
|
560
665
|
- `1 / 0` pasa a ser error;
|
|
561
|
-
- `ARREGLO` pasa a llamarse `lista` en mensajes y en `tipo()
|
|
666
|
+
- `ARREGLO` pasa a llamarse `lista` en mensajes y en `tipo()`;
|
|
667
|
+
- palabras reservadas nuevas (§2.5): `constante`, `dominio`, `repetir`, `veces`, `desde`, `hasta`, `con_paso`,
|
|
668
|
+
`para_cada`, `en`, `romper`, `continuar`, `mod`, `div` y las comparaciones en palabras ya no sirven como nombres;
|
|
669
|
+
- sin `;`, el salto de línea termina la expresión (§2.4): una expresión partida antes de un operador es un error.
|
|
562
670
|
|
|
563
671
|
## 15. Decisiones
|
|
564
672
|
|
|
@@ -583,13 +691,16 @@ Todas aprobadas.
|
|
|
583
691
|
`RuntimeTracer`. Se descartaron los generadores anidados porque, con `yield*`, la recursión profunda
|
|
584
692
|
vuelve a depender de la pila de JavaScript. Incluye `imprimir`, `leer`, `leer_número`, `tipo`, `texto`
|
|
585
693
|
y `número`, porque la entrada y salida son parte del contrato de la máquina.
|
|
586
|
-
4. **Nivel principiante:** `imprimir`/`leer`, `repetir … veces`, `++`/`--`, `%`/`mod`/`div`, `^`,
|
|
587
|
-
operadores en palabras, `constante`, alcance por bloque
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
694
|
+
4. ✅ **Nivel principiante:** `imprimir`/`leer`, `repetir … veces`, `++`/`--`, `%`/`mod`/`div`, `^`,
|
|
695
|
+
operadores en palabras, `constante`, alcance por bloque, `1_000_000` y `PI`. `repetir` emite `decide` con la
|
|
696
|
+
etiqueta `repetir` en cada vuelta y `declara` indica si el nombre es constante.
|
|
697
|
+
5. ✅ **Nivel intermedio:** ✅ procedimientos con nombre, ✅ `para_cada`, ✅ `romper`/`continuar`, ✅ asignación por
|
|
698
|
+
índice (evento `modifica`), ✅ `rango` e `índices`, ✅ diccionarios, ✅ biblioteca de texto y listas (con
|
|
699
|
+
`cost` registrado en cada procedimiento nativo; el cobro llega en el paso 6).
|
|
700
|
+
6. ✅ **Nivel avanzado:** procedimientos como valores, estructuras de datos, costo por operación de la
|
|
591
701
|
biblioteca.
|
|
592
|
-
7. **Modo mundo
|
|
702
|
+
7. ✅ **Modo mundo:** formato JSON versionado con `validateWorld`, `createWorld`, evento `robot`, estado en
|
|
703
|
+
`snapshot()` y objetivos de reto con `checkGoal` (ver [`modo-mundo.md`](./modo-mundo.md)).
|
|
593
704
|
|
|
594
705
|
Cada paso llega con tests y actualiza `lenguaje.md` para que la documentación nunca vuelva a prometer
|
|
595
706
|
lo que el código no hace.
|