UPDATE: Modified LRM and generate_mbap.py to ensure better samples

This commit is contained in:
rafa-ruiz 2026-03-11 20:09:05 -07:00
parent b5167b71e3
commit 90857e1b0a
2 changed files with 138 additions and 45 deletions

View File

@ -115,7 +115,41 @@ AVAP utiliza una gramática estructural mixta. Combina la fluidez de las palabra
La estructura `if()` evalúa una expresión lógica o de comparación. Todo bloque condicional requiere un cierre explícito utilizando el comando `end()`.
El comando `if()` soporta dos modos de invocación:
* **Modo 1 (comparación estructurada):** `if(variable, valor, comparador)` — evalúa la comparación entre variable y valor usando el operador indicado como string (ej. `"=="`, `">"`, `"!="`). Los dos primeros argumentos deben ser identificadores simples o literales, nunca expresiones de acceso como `dict['clave']`. Si se necesita comparar un valor extraído de una estructura, debe asignarse primero a una variable.* **Modo 2 (expresión libre):** `if(None, None, "expresion_compleja")` — evalúa directamente una expresión booleana compleja proporcionada como string.
* **Modo 1 (comparación estructurada):** `if(variable, valor, comparador)` — evalúa la comparación entre variable y valor usando el operador indicado como string (ej. `"=="`, `">"`, `"!="`). Los dos primeros argumentos deben ser identificadores simples o literales, nunca expresiones de acceso como `dict['clave']`. Si se necesita comparar un valor extraído de una estructura, debe asignarse primero a una variable.* **Modo 2 (expresión libre):** `if(None, None, expresion_compleja)` — evalúa directamente una expresión booleana compleja proporcionada como string encapsulado entre `.
## SECCIÓN III: Lógica de Control y Estructuras de Decisión
AVAP utiliza una gramática estructural mixta. Combina la fluidez de las palabras clave para abrir bloques funcionales con la seguridad matemática de cierres estrictos.
### 3.1 El Bloque Condicional (if() / else() / end())
El comando `if()` gestiona la lógica condicional mediante dos modos de invocación estrictamente diferenciados. Es imperativo respetar los delimitadores y la posición de los argumentos.
#### Modo 1: Comparación Estructurada (Atómica)
Se utiliza para comparaciones directas entre dos valores simples.
* **Sintaxis:** `if(átomo_1, átomo_2, "operador")`
* **Argumentos 1 y 2:** Deben ser identificadores simples (variables) o literales (strings/números). **No se permite el uso de `None` en este modo.**
* **Argumento 3:** El operador de comparación debe ir obligatoriamente entre **comillas dobles** (`"=="`, `"!="`, `">"`, `"<"`, `">="`, `"<="`).
* **Restricción:** No se permiten expresiones de acceso (ej. `data.user` o `list[0]`). Estos valores deben asignarse previamente a una variable.
* **Ejemplo correcto:** `if(reintentos, 5, "<")`
#### Modo 2: Expresión Libre (Evaluación Compleja)
Se utiliza para evaluar expresiones lógicas que no encajan en la estructura atómica.
* **Sintaxis:** `if(None, None, `expresión_compleja`)`
* **Argumentos 1 y 2:** Deben ser literalmente la palabra `None` (sin comillas).
* **Argumento 3:** La expresión completa **debe** estar encapsulada entre **acentos graves (backticks)**. Esto permite incluir lógica interna, operadores `and/or` y accesos a estructuras de datos.
* **Ejemplo correcto:** `if(None, None, `user.id > 10 and email.contains("@")`)`
---
### Tabla de Validación para el Modelo
| Entrada | Estado | Razón |
| :--- | :--- | :--- |
| `if(count, 10, "==")` | ✅ VÁLIDO | Modo 1: Átomos válidos y operador entre comillas. |
| `if(None, None, `val > 0`)` | ✅ VÁLIDO | Modo 2: Uso correcto de `None` y backticks. |
| `if(username, None, "==")` | ❌ ERROR | El Modo 1 prohíbe el uso de `None`. Debe usarse el Modo 2. |
| `if(None, None, "val > 0")` | ❌ ERROR | El Modo 2 requiere backticks (`` ` ``), no comillas. |
| `if(user.id, 10, "==")` | ❌ ERROR | El Modo 1 no permite expresiones de acceso (`.`). |
### 3.2 Iteraciones Estrictas y Deterministas (startLoop / endLoop)
Para garantizar el determinismo y evitar el colapso de memoria:
@ -137,15 +171,17 @@ Diseñada para proteger la estabilidad del servidor ante fallos de I/O.
[ "else()" <EOL> <block> ]
"end()" <EOL>
/* if() soporta dos modos:
Modo 1 — comparación estructurada: los dos primeros argumentos deben ser
identificadores simples o literales, nunca expresiones de acceso.
Si se necesita comparar un valor extraído de una estructura (ej. dict['clave']),
debe asignarse previamente a una variable.
Modo 2 — expresión libre: None, None, expresión compleja como string */
<if_condition> ::= <if_atom> "," <if_atom> "," <stringliteral>
| "None" "," "None" "," <stringliteral>
<if_atom> ::= <identifier> | <literal>
<if_condition> ::= <if_structured> | <if_free_expression>
<if_structured> ::= "if" "(" <strict_atom> "," <strict_atom> "," <backtick_string> ")"
<if_free_expression> ::= "if" "(" "None" "," "None" "," <backtick_string> ")"
<strict_atom> ::= <identifier> | <non_null_literal>
<backtick_string> ::= "`" <text_content> "`"
<identifier> ::= [a-zA-Z_][a-zA-Z0-9_]*
<non_null_literal>::= <number> | <string_literal_double_quotes>
/* Nota: <non_null_literal> NO incluye la palabra "None" */
<loop_stmt> ::= "startLoop(" <identifier> "," <expression> "," <expression> ")" <EOL>
<block>
@ -261,59 +297,116 @@ AVAP utiliza `avapConnector("TOKEN")` para la hidratación segura de credenciale
---
## SECCIÓN VI: Utilidades, Criptografía y Manipulación de Datos
# SECCIÓN VI: Utilidades, Criptografía y Manipulación de Datos
AVAP incluye un set de comandos integrados de alto nivel para manipular tipos complejos (JSON y Listas), tiempos, textos y generar hashes.
### 6.1 Manipulación Nativa de Listas y Objetos JSON
Para extraer y mutar estructuras complejas, AVAP provee comandos nativos específicos:
* **`variableToList(elemento, destino)`**: Fuerza a que una variable escalar se convierta en una estructura iterable de lista.
* **`itemFromList(lista_origen, indice, destino)`**: Extrae de forma segura el elemento contenido en la posición `indice` de una lista.
* **`variableFromJSON(json_origen, clave, destino)`**: Parsea un objeto JSON en memoria y extrae el valor correspondiente a la `clave`.
* **`AddVariableToJSON(clave, valor, json_destino)`**: Inyecta dinámicamente una nueva propiedad dentro de un objeto JSON existente.
---
### 6.2 Criptografía y Expresiones Regulares
* **`encodeSHA256` y `encodeMD5(origen, destino)`**: Funciones criptográficas que encriptan de forma irreversible un texto. Vitales para el almacenamiento seguro de contraseñas.
* **`getRegex(origen, patron, destino)`**: Aplica una Expresión Regular (`patron`) sobre la variable de origen, extrayendo las coincidencias exactas.
## 6.1 Manipulación Nativa de Listas y Objetos JSON
### 6.3 Transformación de Tiempo y Cadenas
* **Fechas:** `getTimeStamp` (convierte un string a Epoch), `getDateTime` (Epoch a string legible), y `stampToDatetime` (Epoch a objeto datetime estructurado). Soportan formatos de calendario y cálculos con TimeDeltas.
* **Cadenas:** `replace` (saneamiento y sustitución de texto) y `randomString` (generación determinista de claves/tokens aleatorios).
Para extraer y mutar estructuras complejas, AVAP provee comandos nativos específicos. En AVAP, las listas **no se instancian con literales de array**, sino que se construyen y recorren a través de un conjunto cerrado de comandos especializados:
### Especificación BNF (Sección VI)
* **`variableToList(elemento, destino)`**: Fuerza a que una variable escalar se convierta en una estructura iterable de lista de un único elemento. Es el punto de entrada canónico para construir una lista desde cero a partir de un valor existente.
* **`itemFromList(lista_origen, indice, destino)`**: Extrae de forma segura el elemento contenido en la posición `indice` (base 0) de una lista. Equivale a un acceso por índice controlado.
* **`getListLen(lista, destino)`**: Calcula el número total de elementos contenidos en `lista` y almacena el resultado entero en `destino`. Imprescindible para construir bucles de recorrido seguro y para validar listas antes de acceder a sus índices. Se recomienda llamar siempre a `getListLen` antes de `itemFromList` para evitar accesos fuera de rango.
* **`variableFromJSON(json_origen, clave, destino)`**: Parsea un objeto JSON en memoria y extrae el valor correspondiente a la `clave`, almacenándolo en `destino`. El acceso es directo por nombre de propiedad.
* **`AddVariableToJSON(clave, valor, json_destino)`**: Inyecta dinámicamente una nueva propiedad dentro de un objeto JSON existente. Si la clave ya existe, su valor es sobreescrito.
**Patrón de recorrido típico en AVAP:**
```avap
// 1. Obtener longitud de la lista
getListLen(myList, len)
// 2. Iterar con índice controlado
i = 0
while (i < len) {
itemFromList(myList, i, currentItem)
// ... procesar currentItem ...
i = i + 1
}
```
---
## 6.2 Criptografía y Expresiones Regulares
* **`encodeSHA256(origen, destino)`** y **`encodeMD5(origen, destino)`**: Funciones criptográficas que encriptan de forma irreversible un texto. Vitales para el almacenamiento seguro de contraseñas y la verificación de integridad de datos. SHA-256 produce un digest de 64 caracteres hexadecimales y ofrece mayor resistencia criptográfica que MD5 (32 caracteres); se recomienda SHA-256 para nuevos desarrollos.
* **`getRegex(origen, patron, destino)`**: Aplica una Expresión Regular (`patron`) sobre la variable de origen, extrayendo la primera coincidencia exacta encontrada. El patrón sigue la sintaxis estándar compatible con Python `re`.
---
## 6.3 Transformación de Tiempo y Cadenas
### Fechas y Timestamps
AVAP provee tres comandos complementarios para cubrir todas las conversiones posibles entre representaciones de tiempo. Los tres soportan formatos de calendario en notación `strftime` de Python y cálculos con `TimeDelta` expresados en segundos (positivo para sumar, negativo para restar):
| Comando | Entrada | Salida |
|---|---|---|
| `getTimeStamp(fecha_string, formato, timedelta, destino)` | String de fecha | Epoch (entero) |
| `stampToDatetime(epoch, formato, timedelta, destino)` | Epoch (entero) | String de fecha |
| `getDateTime(formato, timedelta, zona_horaria, destino)` | — (ahora mismo) | String de fecha |
* **`getTimeStamp(fecha_string, formato, timedelta, destino)`**: Convierte un string de fecha legible a su valor Epoch (entero Unix). Útil para almacenar fechas y realizar cálculos aritméticos sobre ellas.
* **`stampToDatetime(epoch, formato, timedelta, destino)`**: Convierte un valor Epoch a un string de fecha con el formato especificado. Útil para presentar timestamps almacenados de forma legible.
* **`getDateTime(formato, timedelta, zona_horaria, destino)`**: Captura la fecha y hora actuales del sistema, aplica el ajuste `timedelta` y las convierte a la `zona_horaria` indicada antes de almacenar el resultado. Acepta cualquier zona horaria reconocida por la librería `pytz` de Python.
### Cadenas de Texto
* **`randomString(patron, longitud, destino)`**: Genera una cadena aleatoria de `longitud` caracteres cuyos símbolos están restringidos al conjunto definido por `patron` (expresión regular de caracteres). Útil para generar tokens de sesión, contraseñas temporales o identificadores únicos.
* **`replace(origen, patron_busqueda, reemplazo, destino)`**: Localiza todas las ocurrencias de `patron_busqueda` dentro de `origen` y las sustituye por `reemplazo`, almacenando el resultado en `destino`. Facilita el saneamiento y normalización de datos de entrada antes de su procesamiento o almacenamiento.
---
## BNF — Gramática Formal de los Comandos de Utilidad
```bnf
/* [CORRECCIÓN] Todas las subreglas de <util_command> están ahora completamente expandidas. */
<util_command> ::= <json_list_cmd> | <crypto_cmd> | <regex_cmd> | <datetime_cmd> | <stamp_cmd> | <string_cmd> | <replace_cmd>
<util_command> ::= <json_list_cmd> | <crypto_cmd> | <regex_cmd>
| <datetime_cmd> | <stamp_cmd> | <string_cmd> | <replace_cmd>
/* Manipulación de listas y JSON */
<json_list_cmd> ::= "variableToList(" <expression> "," <identifier> ")"
| "itemFromList(" <identifier> "," <expression> "," <identifier> ")"
| "variableFromJSON(" <identifier> "," <expression> "," <identifier> ")"
| "AddVariableToJSON(" <expression> "," <expression> "," <identifier> ")"
<json_list_cmd> ::= "variableToList(" <expression> "," <identifier> ")"
| "itemFromList(" <identifier> "," <expression> "," <identifier> ")"
| "getListLen(" <identifier> "," <identifier> ")"
| "variableFromJSON(" <identifier> "," <expression> "," <identifier> ")"
| "AddVariableToJSON(" <expression> "," <expression> "," <identifier> ")"
/* Criptografía */
<crypto_cmd> ::= "encodeSHA256(" <identifier_or_string> "," <identifier> ")"
| "encodeMD5(" <identifier_or_string> "," <identifier> ")"
<crypto_cmd> ::= "encodeSHA256(" <expression> "," <identifier> ")"
| "encodeMD5(" <expression> "," <identifier> ")"
/* Expresiones regulares */
<regex_cmd> ::= "getRegex(" <identifier> "," <stringliteral> "," <identifier> ")"
<regex_cmd> ::= "getRegex(" <identifier> "," <expression> "," <identifier> ")"
<datetime_cmd> ::= "getDateTime(" <stringliteral> "," <expression> "," <stringliteral> "," <identifier> ")"
/* Argumentos: formato_salida, epoch_origen, zona_horaria, destino */
/* Fecha/hora actual → string */
<datetime_cmd> ::= "getDateTime(" <stringliteral> "," <expression> "," <stringliteral> "," <identifier> ")"
/* Argumentos: formato_salida, timedelta, zona_horaria, destino */
<stamp_cmd> ::= "stampToDatetime(" <expression> "," <stringliteral> "," <expression> "," <identifier> ")"
/* Conversiones epoch ↔ string */
<stamp_cmd> ::= "stampToDatetime(" <expression> "," <stringliteral> "," <expression> "," <identifier> ")"
/* Argumentos: epoch_origen, formato, timedelta, destino */
| "getTimeStamp(" <stringliteral> "," <stringliteral> "," <expression> "," <identifier> ")"
| "getTimeStamp(" <stringliteral> "," <stringliteral> "," <expression> "," <identifier> ")"
/* Argumentos: fecha_string, formato_entrada, timedelta, destino */
<string_cmd> ::= "randomString(" <expression> "," <identifier> ")"
/* Argumentos: longitud, destino */
/* Cadenas */
<string_cmd> ::= "randomString(" <expression> "," <expression> "," <identifier> ")"
/* Argumentos: patron, longitud, destino */
<replace_cmd> ::= "replace(" <identifier_or_string> "," <stringliteral> "," <stringliteral> "," <identifier> ")"
<replace_cmd> ::= "replace(" <identifier> "," <stringliteral> "," <stringliteral> "," <identifier> ")"
/* Argumentos: origen, patron_busqueda, reemplazo, destino */
```
---
## SECCIÓN VII: Arquitectura de Funciones y Ámbitos (Scopes)

View File

@ -53,7 +53,7 @@ REGLAS ESTRICTAS para el código AVAP generado:
5. if() Modo 1: if(var_o_literal, var_o_literal, "operador")
los argumentos NO pueden ser expresiones de acceso como dict['key'];
hay que extraer el valor a una variable propia primero.
6. if() Modo 2: if(None, None, "expresion_completa_como_string")
6. if() Modo 2: if(None, None, `expresion_completa_como_string`)
7. _status se asigna con: addVar(_status, 404)
8. ormAccessSelect firma: ormAccessSelect(campos, "tabla", selector, varTarget)
selector puede ser cadena vacía.
@ -105,25 +105,25 @@ Ejemplo sin addParam:
test_list: ["re.match(r'^[a-zA-Z0-9]{16}$', token)"]
FORMATO DE test_list MUY IMPORTANTE:
Cada aserción debe ser una expresión Python con re.match() o re.search()
Cada aserción debe ser una expresión Python con re.match()
evaluable directamente sobre las variables del stack AVAP (disponibles como
variables Python locales). El módulo 're' está siempre disponible.
La expresión debe devolver un match object (truthy) si el test pasa.
Reglas estrictas:
- USA ÚNICAMENTE re.match(r'<patrón>', <variable>) o re.search(r'<patrón>', str(<variable>))
- USA ÚNICAMENTE re.match(r'<patrón>', <variable>)
- NO combines expresiones re.match en una aserción, cada asercion tiene que ser un unico re.match(r'<patrón>', <variable>)
- Convierte a string si es necesario: re.match(r'^\\d+$', str(result))
- Puedes encadenar con 'and': re.match(r'^[a-zA-Z0-9]{32}$', token) and re.match(r'.{32}', token)
- Las variables referenciadas deben existir en el stack tras ejecutar el código.
- NUNCA uses comparaciones directas (==, !=, >, <).
- NUNCA uses isinstance(), len(), assert, ni texto descriptivo.
- NUNCA uses nada que no sea re.match() o re.search().
- NUNCA uses nada que no sea re.match().
Ejemplos correctos de test_list:
"re.match(r'^[a-f0-9]{64}$', hashed)"
"re.match(r'^[a-zA-Z0-9]{32}$', token)"
"re.match(r'^\\d{4}-\\d{2}-\\d{2}$', date_str)"
"re.search(r'Hello', result)"
"re.match(r'^-?\\d+(\\.\\d+)?$', str(result))"
"re.match(r'^(par|impar)$', result)"
"re.match(r'^40[134]$', str(_status))"