Mejorado de solve
This commit is contained in:
parent
1bf1e47c04
commit
ece028e837
|
@ -0,0 +1,234 @@
|
||||||
|
# Guía de Principios Arquitectónicos - Calculadora Algebraica Híbrida
|
||||||
|
|
||||||
|
## Filosofía Central: Álgebra Simbólica con Evaluación Numérica
|
||||||
|
|
||||||
|
### Concepto Fundamental
|
||||||
|
|
||||||
|
La calculadora mantiene **forma simbólica como representación primaria** y proporciona **evaluación numérica como información complementaria** cuando es posible y útil.
|
||||||
|
|
||||||
|
**Principio de Evaluación Numérica**: El resultado siempre se intenta calcular numéricamente y se muestra cuando la representación string del resultado numérico difiere del resultado algebraico.
|
||||||
|
|
||||||
|
## Sistema de Asignaciones y Ecuaciones
|
||||||
|
|
||||||
|
### Principio: Separación clara entre asignaciones y ecuaciones
|
||||||
|
|
||||||
|
```python
|
||||||
|
# Asignación de variable
|
||||||
|
x = 5 # → Se guarda el valor simbólico (NO se agrega como ecuación)
|
||||||
|
y = x + a # → Se guarda la expresión simbólica
|
||||||
|
|
||||||
|
# Ecuación pura (detección automática)
|
||||||
|
x**2 + 2*x = 8 # → Se agrega como ecuación Eq(x**2 + 2*x, 8)
|
||||||
|
a + b = 10 # → Se agrega como ecuación Eq(a + b, 10)
|
||||||
|
a > b + 1 # → Se agrega como desigualdad
|
||||||
|
```
|
||||||
|
|
||||||
|
### Criterios de Detección de Ecuaciones
|
||||||
|
|
||||||
|
**Se considera ecuación si:**
|
||||||
|
|
||||||
|
- Contiene `=` Y NO es una asignación simple de variable
|
||||||
|
- Contiene operadores de comparación: `==`, `>`, `<`, `>=`, `<=`
|
||||||
|
- Tiene estructura algebraica en ambos lados del `=`
|
||||||
|
|
||||||
|
**NO se considera ecuación:**
|
||||||
|
|
||||||
|
- Asignaciones simples: `x = 5`, `y = expresión`
|
||||||
|
- Líneas con solo números o comentarios
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Uso de `solve()` y el Atajo `=?`
|
||||||
|
|
||||||
|
### Principio: `variable=?` es equivalente a `solve(variable)`
|
||||||
|
|
||||||
|
```python
|
||||||
|
# Ambas formas son idénticas:
|
||||||
|
solve(a) # Resuelve 'a' usando el sistema de ecuaciones
|
||||||
|
a=? # Atajo sintáctico para solve(a)
|
||||||
|
```
|
||||||
|
|
||||||
|
El comando intenta resolver algebraicamente y numéricamente en paralelo cuando es posible.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Sistema de Tokenización con Prioridades
|
||||||
|
|
||||||
|
### Principio: Las prioridades son números arbitrarios que determinan el orden de aplicación
|
||||||
|
|
||||||
|
```
|
||||||
|
Prioridad 5: IntBase → Patrón: 16#FF (muy específico)
|
||||||
|
Prioridad 6: Hex/Bin → Patrón: 0xFF, 0b1010 (específico)
|
||||||
|
Prioridad 10: FourBytes → Patrón: x.x.x.x (general)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Regla**: Menor número = se aplica primero
|
||||||
|
|
||||||
|
Esto garantiza que `16#10.10.10.10` se tokenice como IntBase antes de considerar FourBytes.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Conversión Perezosa y Tipos Especializados
|
||||||
|
|
||||||
|
### Principio: Mantener el tipo especializado siempre que sea posible
|
||||||
|
|
||||||
|
**Se evita convertir a SymPy al máximo**. Los objetos especializados mantienen su tipo cuando pueden resolver la operación internamente.
|
||||||
|
|
||||||
|
```python
|
||||||
|
# Operaciones que mantienen el tipo especializado:
|
||||||
|
Hex(15) + 1 → Hex(16) # Hex maneja la suma
|
||||||
|
16#15 + 1 → 16#16 # IntBase maneja la suma
|
||||||
|
10.1.1.1 + 1 → 10.1.1.2 # FourBytes maneja la suma
|
||||||
|
|
||||||
|
# Conversión a SymPy solo cuando es necesario:
|
||||||
|
sin(16#FF) → sin(255) # sin() requiere SymPy
|
||||||
|
solve(x + 16#10) → solve() # Álgebra compleja requiere SymPy
|
||||||
|
```
|
||||||
|
|
||||||
|
**Regla**: Solo se convierte a SymPy cuando el token no es atómico o la operación requiere capacidades algebraicas avanzadas.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Contexto Limpio por Evaluación
|
||||||
|
|
||||||
|
### Principio: Cada evaluación comienza desde cero
|
||||||
|
|
||||||
|
**Contexto Limpio** significa:
|
||||||
|
|
||||||
|
- Se eliminan todas las ecuaciones previas
|
||||||
|
- Se eliminan todas las variables definidas
|
||||||
|
- Se re-evalúa todo el contenido línea por línea
|
||||||
|
- Comportamiento idéntico a iniciar una nueva sesión
|
||||||
|
|
||||||
|
Esto garantiza resultados predecibles y sin efectos secundarios acumulados.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Resultados Interactivos
|
||||||
|
|
||||||
|
### Principio: Activación mediante clicks en elementos con binding
|
||||||
|
|
||||||
|
Los resultados interactivos se crean cuando el tipo de resultado requiere visualización expandida:
|
||||||
|
|
||||||
|
```python
|
||||||
|
plot(sin(x)) → "📊 Ver Plot" # Click abre ventana matplotlib
|
||||||
|
Matrix([[1,2],[3,4]]) → "📋 Ver Matriz" # Click muestra matriz formateada
|
||||||
|
[1,2,3,4,5,6,7,8] → "📋 Ver Lista" # Click expande contenido
|
||||||
|
```
|
||||||
|
|
||||||
|
**Activación**: Click en el texto con binding dispara la ventana emergente correspondiente.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Sistema de Autocompletado
|
||||||
|
|
||||||
|
### Principio: Sistema extensible con prioridades (por implementar)
|
||||||
|
|
||||||
|
Se propone usar un sistema de prioridades numéricas similar al de tokenización:
|
||||||
|
|
||||||
|
```
|
||||||
|
Prioridad 1: Métodos del objeto específico
|
||||||
|
Prioridad 2: Métodos de la clase base
|
||||||
|
Prioridad 3: Funciones SymPy relevantes
|
||||||
|
Prioridad 4: Helpers contextuales
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Integración con SymPy
|
||||||
|
|
||||||
|
### Principio: En casos de conflicto, siempre prevalece SymPy
|
||||||
|
|
||||||
|
Cuando hay ambigüedad o conflicto entre tipos personalizados y SymPy:
|
||||||
|
|
||||||
|
- Funciones SymPy tienen precedencia
|
||||||
|
- Símbolos SymPy (como `e`, `pi`) mantienen su significado matemático
|
||||||
|
- Las conversiones fallidas retornan a comportamiento SymPy estándar
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Arquitectura de Tipos Personalizados
|
||||||
|
|
||||||
|
### Clases Base Universales
|
||||||
|
|
||||||
|
**IntBase**: Números en cualquier base
|
||||||
|
|
||||||
|
- Aritmética nativa que preserva la base
|
||||||
|
- Conversión a SymPy solo cuando necesario
|
||||||
|
- Soporte para símbolos algebraicos
|
||||||
|
|
||||||
|
**FourBytes**: Patrones x.x.x.x
|
||||||
|
|
||||||
|
- Aritmética de 32-bit para IPs
|
||||||
|
- Soporte para elementos simbólicos
|
||||||
|
- Base para tipos como IP4
|
||||||
|
|
||||||
|
### Principio de Extensibilidad
|
||||||
|
|
||||||
|
Cada tipo en `custom_types/` define:
|
||||||
|
|
||||||
|
1. Su lógica de tokenización
|
||||||
|
2. Sus operaciones aritméticas
|
||||||
|
3. Sus métodos de conversión
|
||||||
|
4. Su ayuda contextual
|
||||||
|
5. Sus sugerencias de autocompletado
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Flujo de Evaluación Completo
|
||||||
|
|
||||||
|
```
|
||||||
|
Entrada Usuario
|
||||||
|
↓
|
||||||
|
[Tokenización Universal]
|
||||||
|
↓
|
||||||
|
¿Asignación o Ecuación?
|
||||||
|
├─ Asignación → Guardar valor simbólico
|
||||||
|
└─ Ecuación → Agregar al sistema
|
||||||
|
↓
|
||||||
|
[Evaluación]
|
||||||
|
├─ Mantener tipo especializado si es posible
|
||||||
|
└─ Convertir a SymPy si es necesario
|
||||||
|
↓
|
||||||
|
[Resultado]
|
||||||
|
├─ Forma simbólica (siempre)
|
||||||
|
└─ Evaluación numérica (si difiere como string)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Ejemplos Integrales
|
||||||
|
|
||||||
|
```python
|
||||||
|
# Tokenización y tipos especializados
|
||||||
|
16#FF + 2#1010 → 16#109 # IntBase preservado
|
||||||
|
192.168.1.1 + 5 → 192.168.1.6 # FourBytes preservado
|
||||||
|
|
||||||
|
# Asignaciones vs ecuaciones
|
||||||
|
x = 10 # Asignación (solo guarda valor)
|
||||||
|
x + y = 15 # Ecuación (se agrega al sistema)
|
||||||
|
y=? # solve(y) → y = 5
|
||||||
|
|
||||||
|
# Evaluación numérica automática
|
||||||
|
4/5 → 4/5 ≈ 0.8 # Difiere como string
|
||||||
|
sqrt(2) → √2 ≈ 1.414 # Difiere como string
|
||||||
|
2 + 3 → 5 # NO se muestra ≈ (igual string)
|
||||||
|
|
||||||
|
# Resultados interactivos
|
||||||
|
plot(sin(x)) → "📊 Ver Plot" [clickeable]
|
||||||
|
Matrix([[1,2]]) → "📋 Ver Matriz" [clickeable]
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Principios de Diseño Resumidos
|
||||||
|
|
||||||
|
1. **Álgebra primero**: Mantener forma simbólica siempre
|
||||||
|
2. **Evaluación numérica inteligente**: Mostrar solo cuando agrega valor
|
||||||
|
3. **Tipos especializados preservados**: Conversión a SymPy solo cuando necesario
|
||||||
|
4. **Tokenización ordenada**: Sistema de prioridades simple y predecible
|
||||||
|
5. **Contexto limpio**: Cada evaluación desde cero
|
||||||
|
6. **Extensibilidad**: Nuevos tipos se integran automáticamente
|
||||||
|
7. **SymPy prevalece**: En conflictos, el comportamiento matemático estándar gana
|
||||||
|
|
||||||
|
Este documento ahora refleja con precisión la arquitectura implementada y sirve como guía coherente para el desarrollo futuro.
|
|
@ -2,12 +2,16 @@
|
||||||
|
|
||||||
## Propósito
|
## Propósito
|
||||||
|
|
||||||
Esta API permite debuggear la **Calculadora MAV CAS** sin modificar código fuente ni crear scripts adicionales. Como LLM, puedes usar esta herramienta para:
|
Esta API permite debuggear la **Calculadora MAV CAS** sin modificar código fuente ni crear scripts adicionales.
|
||||||
|
|
||||||
|
**Principio**: **texto → texto** tal como se muestra en la aplicación.
|
||||||
|
**NO duplica lógica**, solo encapsula llamadas directas al motor existente.
|
||||||
|
|
||||||
|
Como LLM, puedes usar esta herramienta para:
|
||||||
|
|
||||||
- **Diagnosticar problemas** en el motor de evaluación
|
- **Diagnosticar problemas** en el motor de evaluación
|
||||||
- **Verificar comportamiento** de tipos personalizados (FourBytes, IntBase, IP4Mask, etc.)
|
- **Verificar comportamiento** de tipos personalizados (FourBytes, IntBase, IP4Mask, etc.)
|
||||||
- **Inspeccionar el estado interno** del motor (variables, contexto, tipos registrados)
|
- **Inspeccionar el estado interno** del motor (variables, contexto, tipos registrados)
|
||||||
- **Analizar el formato de salida** exacto como se muestra en la aplicación
|
|
||||||
- **Testing de regresión** para verificar que cambios no rompan funcionalidad existente
|
- **Testing de regresión** para verificar que cambios no rompan funcionalidad existente
|
||||||
|
|
||||||
## Flujo de Trabajo Recomendado
|
## Flujo de Trabajo Recomendado
|
||||||
|
@ -22,6 +26,7 @@ Esta API permite debuggear la **Calculadora MAV CAS** sin modificar código fuen
|
||||||
|
|
||||||
### Query tipo `input`
|
### Query tipo `input`
|
||||||
Evalúa expresiones como si el usuario las escribiera en la calculadora.
|
Evalúa expresiones como si el usuario las escribiera en la calculadora.
|
||||||
|
**Resultado**: texto tal como se muestra en la aplicación.
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{"index": 0, "type": "input", "content": "10.1.1.1 + 1"}
|
{"index": 0, "type": "input", "content": "10.1.1.1 + 1"}
|
||||||
|
@ -29,6 +34,7 @@ Evalúa expresiones como si el usuario las escribiera en la calculadora.
|
||||||
|
|
||||||
### Query tipo `exec`
|
### Query tipo `exec`
|
||||||
Ejecuta código Python para inspeccionar el estado interno del motor.
|
Ejecuta código Python para inspeccionar el estado interno del motor.
|
||||||
|
**Resultado**: valor directo de la evaluación Python.
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{"index": 1, "type": "exec", "content": "type(engine.last_result).__name__"}
|
{"index": 1, "type": "exec", "content": "type(engine.last_result).__name__"}
|
||||||
|
@ -126,7 +132,7 @@ Ejecuta código Python para inspeccionar el estado interno del motor.
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"execution_info": {
|
"execution_info": {
|
||||||
"timestamp": "2025-06-05T18:01:28.644799Z",
|
"timestamp": "2025-06-05T18:25:22.256442Z",
|
||||||
"total_queries": 5,
|
"total_queries": 5,
|
||||||
"successful": 4,
|
"successful": 4,
|
||||||
"failed": 1
|
"failed": 1
|
||||||
|
@ -141,22 +147,10 @@ Ejecuta código Python para inspeccionar el estado interno del motor.
|
||||||
{
|
{
|
||||||
"index": 0,
|
"index": 0,
|
||||||
"input": "10.1.1.1 + 1",
|
"input": "10.1.1.1 + 1",
|
||||||
"output": "10.1.1.2", // Resultado básico
|
"output": "10.1.1.2", // Texto tal como se muestra en la app
|
||||||
"result_type": "FourBytes", // Tipo del objeto resultado
|
"result_type": "FourBytes", // Tipo del objeto resultado
|
||||||
"success": true,
|
"success": true,
|
||||||
"error": null,
|
"error": null
|
||||||
"display_class": "[FourBytes]", // Nombre de clase para display
|
|
||||||
"output_raw": { // ⭐ INFORMACIÓN DE FORMATO
|
|
||||||
"parts": [
|
|
||||||
["custom_type", "10.1.1.2"], // [tag_color, contenido]
|
|
||||||
["class_hint", "[FourBytes]"]
|
|
||||||
],
|
|
||||||
"formatted_text": "[custom_type]10.1.1.2[class_hint][FourBytes]",
|
|
||||||
"tag_info": { // Información de colores
|
|
||||||
"custom_type": {"fg": "#f9a825"},
|
|
||||||
"class_hint": {"fg": "#888888"}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -166,11 +160,11 @@ Ejecuta código Python para inspeccionar el estado interno del motor.
|
||||||
{
|
{
|
||||||
"index": 1,
|
"index": 1,
|
||||||
"input": "type(engine.last_result).__name__",
|
"input": "type(engine.last_result).__name__",
|
||||||
"output": "FourBytes",
|
"output": "FourBytes", // String del resultado
|
||||||
"result_type": "str",
|
"result_type": "str", // Tipo del resultado de la evaluación
|
||||||
"success": true,
|
"success": true,
|
||||||
"error": null,
|
"error": null,
|
||||||
"exec_result": "FourBytes" // Resultado crudo del exec
|
"exec_result": "FourBytes" // Valor directo (serializado si es necesario)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -183,12 +177,7 @@ Ejecuta código Python para inspeccionar el estado interno del motor.
|
||||||
"output": "None",
|
"output": "None",
|
||||||
"result_type": "NoneType",
|
"result_type": "NoneType",
|
||||||
"success": false,
|
"success": false,
|
||||||
"error": "❌ Máscara inválida: 255.240.0.3...",
|
"error": "❌ Máscara inválida: 255.240.0.3..."
|
||||||
"output_raw": {
|
|
||||||
"parts": [["error", "Error: ❌ Máscara inválida..."]],
|
|
||||||
"formatted_text": "[error]Error: ❌ Máscara inválida...",
|
|
||||||
"tag_info": {"error": {"fg": "#ff6b6b", "font": "bold"}}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -297,9 +286,9 @@ Ejecuta código Python para inspeccionar el estado interno del motor.
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 4. Debugging de Display/Formato
|
### 4. Debugging de Comportamiento
|
||||||
|
|
||||||
**Cuándo usar**: Verificar cómo se muestra exactamente un resultado.
|
**Cuándo usar**: Verificar comportamiento específico de tipos o funciones.
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
@ -314,33 +303,6 @@ Ejecuta código Python para inspeccionar el estado interno del motor.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Análisis de output_raw
|
|
||||||
|
|
||||||
El campo `output_raw` contiene información exacta sobre cómo se muestra el resultado en la aplicación:
|
|
||||||
|
|
||||||
### Tags de Color Importantes
|
|
||||||
|
|
||||||
- **`error`** (`#ff6b6b`): Errores
|
|
||||||
- **`custom_type`** (`#f9a825`): Tipos personalizados (FourBytes, IntBase, etc.)
|
|
||||||
- **`symbolic`** (`#82aaff`): Expresiones simbólicas
|
|
||||||
- **`numeric`** (`#c3e88d`): Aproximaciones numéricas
|
|
||||||
- **`class_hint`** (`#888888`): Pistas de clase `[FourBytes]`
|
|
||||||
- **`ip`** (`#fff176`): Direcciones IP específicamente
|
|
||||||
- **`hex`** (`#f9a825`): Números hexadecimales
|
|
||||||
|
|
||||||
### Interpretación de Parts
|
|
||||||
|
|
||||||
```json
|
|
||||||
"parts": [
|
|
||||||
["custom_type", "192.168.1.2"], // Resultado principal en naranja
|
|
||||||
["class_hint", "[FourBytes]"] // Pista de clase en gris
|
|
||||||
]
|
|
||||||
```
|
|
||||||
|
|
||||||
Esto significa: "192.168.1.2" se muestra en color naranjo seguido de "[FourBytes]" en gris.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Comandos de Ejecución
|
## Comandos de Ejecución
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
@ -375,11 +337,6 @@ python simple_debug.py mi_debug.json --verbose
|
||||||
- Tipos registrados
|
- Tipos registrados
|
||||||
- Sistema de ecuaciones
|
- Sistema de ecuaciones
|
||||||
|
|
||||||
### Formato de Display
|
|
||||||
**Archivo**: `debug_templates/display_format_test.json`
|
|
||||||
- Demostración de `output_raw`
|
|
||||||
- Diferentes tipos de formato
|
|
||||||
|
|
||||||
### Tokenización
|
### Tokenización
|
||||||
**Archivo**: `debug_templates/tokenization_test.json`
|
**Archivo**: `debug_templates/tokenization_test.json`
|
||||||
- Debug del sistema de parsing
|
- Debug del sistema de parsing
|
||||||
|
@ -391,7 +348,6 @@ python simple_debug.py mi_debug.json --verbose
|
||||||
|
|
||||||
### 1. Identificar el Problema
|
### 1. Identificar el Problema
|
||||||
- ¿Es un error de evaluación?
|
- ¿Es un error de evaluación?
|
||||||
- ¿Es un problema de formato/display?
|
|
||||||
- ¿Es un problema de tokenización?
|
- ¿Es un problema de tokenización?
|
||||||
- ¿Es un problema de estado del motor?
|
- ¿Es un problema de estado del motor?
|
||||||
|
|
||||||
|
@ -402,8 +358,7 @@ python simple_debug.py mi_debug.json --verbose
|
||||||
### 3. Analizar Resultados
|
### 3. Analizar Resultados
|
||||||
- Verificar `success: true/false`
|
- Verificar `success: true/false`
|
||||||
- Examinar `error` si hay fallo
|
- Examinar `error` si hay fallo
|
||||||
- Analizar `output_raw` para problemas de display
|
- Comparar `output` (texto de la app) con `exec_result` (valor interno)
|
||||||
- Usar `exec_result` para inspección detallada
|
|
||||||
|
|
||||||
### 4. Iterar
|
### 4. Iterar
|
||||||
- Crear nuevas queries basadas en hallazgos
|
- Crear nuevas queries basadas en hallazgos
|
||||||
|
@ -438,8 +393,8 @@ python simple_debug.py debug_problema.json
|
||||||
```
|
```
|
||||||
|
|
||||||
### Paso 3: Analizar resultados
|
### Paso 3: Analizar resultados
|
||||||
- Verificar si `192.168.1.x + 1` se evalúa correctamente
|
- Verificar si `192.168.1.x + 1` se evalúa correctamente (campo `output`)
|
||||||
- Comprobar el tipo resultante
|
- Comprobar el tipo resultante con `exec`
|
||||||
- Verificar si tiene símbolos
|
- Verificar si tiene símbolos
|
||||||
- Examinar cómo se tokeniza la expresión
|
- Examinar cómo se tokeniza la expresión
|
||||||
- Probar operaciones relacionadas
|
- Probar operaciones relacionadas
|
||||||
|
@ -452,13 +407,12 @@ Este flujo te permite identificar exactamente dónde está el problema y verific
|
||||||
|
|
||||||
1. **Siempre usa índices secuenciales** en las queries para facilitar la lectura
|
1. **Siempre usa índices secuenciales** en las queries para facilitar la lectura
|
||||||
2. **Combina queries `input` y `exec`** para obtener contexto completo
|
2. **Combina queries `input` y `exec`** para obtener contexto completo
|
||||||
3. **Verifica tanto `output` como `output_raw`** para problemas de display
|
3. **El campo `output` es texto tal como se muestra en la aplicación**
|
||||||
4. **Usa los templates existentes** como punto de partida
|
4. **El campo `exec_result` es el valor directo de la evaluación Python**
|
||||||
5. **Examina `success` y `error`** antes de analizar resultados
|
5. **Usa los templates existentes** como punto de partida
|
||||||
6. **Aprovecha `exec_result`** para inspección detallada del estado
|
6. **Examina `success` y `error`** antes de analizar resultados
|
||||||
7. **Crea queries incrementales** que construyan sobre resultados anteriores
|
7. **Crea queries incrementales** que construyan sobre resultados anteriores
|
||||||
|
8. **NO intentes duplicar lógica de la aplicación** - usa solo llamadas directas
|
||||||
Con esta API, puedes debuggear efectivamente la calculadora sin necesidad de modificar código fuente o crear scripts adicionales.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -489,9 +443,8 @@ python simple_debug.py archivo.json -o resultado.json # Salida específica
|
||||||
```python
|
```python
|
||||||
"success": true/false # ¿Éxito?
|
"success": true/false # ¿Éxito?
|
||||||
"error": "mensaje" # Error si falla
|
"error": "mensaje" # Error si falla
|
||||||
"output": "resultado" # Resultado básico
|
"output": "resultado" # Texto tal como se muestra en la app
|
||||||
"output_raw": {...} # Formato exacto de la app
|
"exec_result": valor # Valor directo (exec queries)
|
||||||
"exec_result": valor # Resultado crudo (exec queries)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Templates Disponibles
|
### Templates Disponibles
|
||||||
|
@ -499,10 +452,11 @@ python simple_debug.py archivo.json -o resultado.json # Salida específica
|
||||||
- `debug_templates/error_debug.json` - Testing de errores
|
- `debug_templates/error_debug.json` - Testing de errores
|
||||||
- `debug_templates/context_debug.json` - Estado del motor
|
- `debug_templates/context_debug.json` - Estado del motor
|
||||||
- `debug_templates/tokenization_test.json` - Debug de parsing
|
- `debug_templates/tokenization_test.json` - Debug de parsing
|
||||||
- `debug_templates/display_format_test.json` - Formato de display
|
|
||||||
|
|
||||||
### Workflow Típico
|
### Workflow Típico
|
||||||
1. **Identificar problema** → Crear query `input` para reproducir
|
1. **Identificar problema** → Crear query `input` para reproducir
|
||||||
2. **Inspeccionar estado** → Añadir queries `exec` para diagnosticar
|
2. **Inspeccionar estado** → Añadir queries `exec` para diagnosticar
|
||||||
3. **Analizar resultados** → Examinar `success`, `error`, `output_raw`
|
3. **Analizar resultados** → Examinar `success`, `error`, `output`
|
||||||
4. **Iterar** → Crear nuevas queries basadas en hallazgos
|
4. **Iterar** → Crear nuevas queries basadas en hallazgos
|
||||||
|
|
||||||
|
**Principio clave**: texto → texto. La API no interpreta ni procesa, solo encapsula llamadas directas al motor existente.
|
|
@ -1,462 +0,0 @@
|
||||||
# Simple Debug API - Guía para LLM
|
|
||||||
|
|
||||||
## Propósito
|
|
||||||
|
|
||||||
Esta API permite debuggear la **Calculadora MAV CAS** sin modificar código fuente ni crear scripts adicionales.
|
|
||||||
|
|
||||||
**Principio**: **texto → texto** tal como se muestra en la aplicación.
|
|
||||||
**NO duplica lógica**, solo encapsula llamadas directas al motor existente.
|
|
||||||
|
|
||||||
Como LLM, puedes usar esta herramienta para:
|
|
||||||
|
|
||||||
- **Diagnosticar problemas** en el motor de evaluación
|
|
||||||
- **Verificar comportamiento** de tipos personalizados (FourBytes, IntBase, IP4Mask, etc.)
|
|
||||||
- **Inspeccionar el estado interno** del motor (variables, contexto, tipos registrados)
|
|
||||||
- **Testing de regresión** para verificar que cambios no rompan funcionalidad existente
|
|
||||||
|
|
||||||
## Flujo de Trabajo Recomendado
|
|
||||||
|
|
||||||
### 1. Crear archivo JSON con queries
|
|
||||||
### 2. Ejecutar: `python simple_debug.py archivo.json`
|
|
||||||
### 3. Analizar resultados en el archivo `*_results.json`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Tipos de Query
|
|
||||||
|
|
||||||
### Query tipo `input`
|
|
||||||
Evalúa expresiones como si el usuario las escribiera en la calculadora.
|
|
||||||
**Resultado**: texto tal como se muestra en la aplicación.
|
|
||||||
|
|
||||||
```json
|
|
||||||
{"index": 0, "type": "input", "content": "10.1.1.1 + 1"}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Query tipo `exec`
|
|
||||||
Ejecuta código Python para inspeccionar el estado interno del motor.
|
|
||||||
**Resultado**: valor directo de la evaluación Python.
|
|
||||||
|
|
||||||
```json
|
|
||||||
{"index": 1, "type": "exec", "content": "type(engine.last_result).__name__"}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Plantilla Base
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"queries": [
|
|
||||||
{"index": 0, "type": "input", "content": "EXPRESION_A_EVALUAR"},
|
|
||||||
{"index": 1, "type": "exec", "content": "CODIGO_PYTHON_INSPECCION"}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Casos de Uso Comunes
|
|
||||||
|
|
||||||
### Debugging de Tipos Personalizados
|
|
||||||
|
|
||||||
**Problema**: Verificar si FourBytes maneja correctamente operaciones IP.
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"queries": [
|
|
||||||
{"index": 0, "type": "input", "content": "192.168.1.1 + 1"},
|
|
||||||
{"index": 1, "type": "exec", "content": "type(engine.last_result).__name__"},
|
|
||||||
{"index": 2, "type": "exec", "content": "engine.last_result.original"},
|
|
||||||
{"index": 3, "type": "exec", "content": "engine.last_result._numeric_value"},
|
|
||||||
{"index": 4, "type": "input", "content": "10.0.0.0/8 + 256"},
|
|
||||||
{"index": 5, "type": "exec", "content": "engine.last_result.has_symbols"}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Debugging de Tokenización
|
|
||||||
|
|
||||||
**Problema**: La expresión `192.168.1.x + 16#FF` no se tokeniza correctamente.
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"queries": [
|
|
||||||
{"index": 0, "type": "exec", "content": "engine.parser.process_expression('192.168.1.x + 16#FF')"},
|
|
||||||
{"index": 1, "type": "input", "content": "192.168.1.x + 16#FF"},
|
|
||||||
{"index": 2, "type": "exec", "content": "engine.parser.get_tokenization_info()"},
|
|
||||||
{"index": 3, "type": "exec", "content": "len(engine.parser.tokenizer.tokenization_rules)"}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Debugging de Errores
|
|
||||||
|
|
||||||
**Problema**: IP4Mask rechaza máscaras que deberían ser válidas.
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"queries": [
|
|
||||||
{"index": 0, "type": "input", "content": "mask = 255.240.0.0"},
|
|
||||||
{"index": 1, "type": "input", "content": "IP4Mask(mask)"},
|
|
||||||
{"index": 2, "type": "exec", "content": "engine.last_result"},
|
|
||||||
{"index": 3, "type": "input", "content": "IP4Mask(255.240.0.3)"},
|
|
||||||
{"index": 4, "type": "exec", "content": "engine.last_result"}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Debugging de Estado del Motor
|
|
||||||
|
|
||||||
**Problema**: Las variables no se están guardando correctamente.
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"queries": [
|
|
||||||
{"index": 0, "type": "input", "content": "x = 5"},
|
|
||||||
{"index": 1, "type": "input", "content": "y = x + 10"},
|
|
||||||
{"index": 2, "type": "exec", "content": "engine.symbol_table"},
|
|
||||||
{"index": 3, "type": "exec", "content": "len(engine.symbol_table)"},
|
|
||||||
{"index": 4, "type": "exec", "content": "list(engine.symbol_table.keys())"},
|
|
||||||
{"index": 5, "type": "input", "content": "solve(z**2 + x, z)"},
|
|
||||||
{"index": 6, "type": "exec", "content": "len(engine.equations)"}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Interpretación de Resultados
|
|
||||||
|
|
||||||
### Estructura del Resultado
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"execution_info": {
|
|
||||||
"timestamp": "2025-06-05T18:25:22.256442Z",
|
|
||||||
"total_queries": 5,
|
|
||||||
"successful": 4,
|
|
||||||
"failed": 1
|
|
||||||
},
|
|
||||||
"results": [...]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Resultado Individual (Query `input`)
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"index": 0,
|
|
||||||
"input": "10.1.1.1 + 1",
|
|
||||||
"output": "10.1.1.2", // Texto tal como se muestra en la app
|
|
||||||
"result_type": "FourBytes", // Tipo del objeto resultado
|
|
||||||
"success": true,
|
|
||||||
"error": null
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Resultado Individual (Query `exec`)
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"index": 1,
|
|
||||||
"input": "type(engine.last_result).__name__",
|
|
||||||
"output": "FourBytes", // String del resultado
|
|
||||||
"result_type": "str", // Tipo del resultado de la evaluación
|
|
||||||
"success": true,
|
|
||||||
"error": null,
|
|
||||||
"exec_result": "FourBytes" // Valor directo (serializado si es necesario)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Resultado con Error
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"index": 2,
|
|
||||||
"input": "IP4Mask(255.240.0.3)",
|
|
||||||
"output": "None",
|
|
||||||
"result_type": "NoneType",
|
|
||||||
"success": false,
|
|
||||||
"error": "❌ Máscara inválida: 255.240.0.3..."
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Funciones de Inspección Útiles
|
|
||||||
|
|
||||||
### Estado del Motor
|
|
||||||
|
|
||||||
```python
|
|
||||||
"engine.symbol_table" # Variables actuales
|
|
||||||
"engine.last_result" # Último resultado
|
|
||||||
"engine.symbolic_mode" # ¿Modo simbólico activo?
|
|
||||||
"len(engine.equations)" # Cantidad de ecuaciones en el sistema
|
|
||||||
"engine.debug" # ¿Debug habilitado?
|
|
||||||
"list(engine.base_context.keys())[:10]" # Funciones disponibles (muestra 10)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Información de Tipos
|
|
||||||
|
|
||||||
```python
|
|
||||||
"engine.get_available_types()" # Info completa de tipos registrados
|
|
||||||
"list(engine.registered_types_info['registered_classes'].keys())" # Lista de tipos
|
|
||||||
"engine.registered_types_info['class_count']" # Cantidad de tipos registrados
|
|
||||||
"type(engine.last_result).__name__" # Tipo del último resultado
|
|
||||||
"hasattr(engine.last_result, 'has_symbols')" # ¿El resultado tiene símbolos?
|
|
||||||
```
|
|
||||||
|
|
||||||
### Tokenización y Parsing
|
|
||||||
|
|
||||||
```python
|
|
||||||
"engine.parser.get_tokenization_info()" # Info completa de tokenización
|
|
||||||
"engine.parser.process_expression('test')" # Procesar expresión específica
|
|
||||||
"len(engine.parser.tokenizer.tokenization_rules)" # Cantidad de reglas
|
|
||||||
"engine._classify_line('x = 5')" # Clasificar tipo de línea
|
|
||||||
"engine._extract_variable_names('x + y')" # Extraer nombres de variables
|
|
||||||
```
|
|
||||||
|
|
||||||
### Análisis de Objetos Específicos
|
|
||||||
|
|
||||||
```python
|
|
||||||
# Para FourBytes
|
|
||||||
"engine.last_result.original" # String original
|
|
||||||
"engine.last_result._numeric_value" # Valor numérico interno
|
|
||||||
"engine.last_result.has_symbols" # ¿Tiene símbolos?
|
|
||||||
|
|
||||||
# Para IntBase
|
|
||||||
"engine.last_result.base" # Base numérica (10, 16, 8, 2)
|
|
||||||
"engine.last_result.value_str" # String del valor
|
|
||||||
"engine.last_result._symbols" # Símbolos detectados
|
|
||||||
|
|
||||||
# Para IP4Mask
|
|
||||||
"engine.last_result.get_prefix_int()" # Prefijo como entero
|
|
||||||
"engine.last_result.is_valid()" # ¿Es máscara válida?
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Patrones de Debugging
|
|
||||||
|
|
||||||
### 1. Debugging de Regresión
|
|
||||||
|
|
||||||
**Cuándo usar**: Verificar que cambios no rompan funcionalidad existente.
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"queries": [
|
|
||||||
{"index": 0, "type": "input", "content": "10.1.1.1 + 1"},
|
|
||||||
{"index": 1, "type": "exec", "content": "type(engine.last_result).__name__"},
|
|
||||||
{"index": 2, "type": "input", "content": "16#FF + 10"},
|
|
||||||
{"index": 3, "type": "exec", "content": "engine.last_result.base"},
|
|
||||||
{"index": 4, "type": "input", "content": "IP4Mask(255.255.0.0)"},
|
|
||||||
{"index": 5, "type": "exec", "content": "engine.last_result.get_prefix_int()"}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Debugging de Nuevas Funcionalidades
|
|
||||||
|
|
||||||
**Cuándo usar**: Verificar que nueva funcionalidad trabaja correctamente.
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"queries": [
|
|
||||||
{"index": 0, "type": "input", "content": "NUEVA_FUNCIONALIDAD_AQUI"},
|
|
||||||
{"index": 1, "type": "exec", "content": "type(engine.last_result)"},
|
|
||||||
{"index": 2, "type": "exec", "content": "dir(engine.last_result)"},
|
|
||||||
{"index": 3, "type": "exec", "content": "str(engine.last_result)"},
|
|
||||||
{"index": 4, "type": "exec", "content": "engine.symbol_table"}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Debugging de Performance
|
|
||||||
|
|
||||||
**Cuándo usar**: Identificar operaciones lentas o problemáticas.
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"queries": [
|
|
||||||
{"index": 0, "type": "exec", "content": "import time; start = time.time()"},
|
|
||||||
{"index": 1, "type": "input", "content": "OPERACION_LENTA"},
|
|
||||||
{"index": 2, "type": "exec", "content": "time.time() - start"},
|
|
||||||
{"index": 3, "type": "exec", "content": "len(engine.symbol_table)"}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. Debugging de Comportamiento
|
|
||||||
|
|
||||||
**Cuándo usar**: Verificar comportamiento específico de tipos o funciones.
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"queries": [
|
|
||||||
{"index": 0, "type": "input", "content": "EXPRESION"},
|
|
||||||
{"index": 1, "type": "exec", "content": "str(engine.last_result)"},
|
|
||||||
{"index": 2, "type": "exec", "content": "repr(engine.last_result)"},
|
|
||||||
{"index": 3, "type": "exec", "content": "type(engine.last_result).__name__"}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Comandos de Ejecución
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Ejecución básica
|
|
||||||
python simple_debug.py mi_debug.json
|
|
||||||
|
|
||||||
# Con archivo de salida específico
|
|
||||||
python simple_debug.py mi_debug.json --output resultados.json
|
|
||||||
|
|
||||||
# Modo verboso (para ver progreso)
|
|
||||||
python simple_debug.py mi_debug.json --verbose
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Templates Existentes para Reutilizar
|
|
||||||
|
|
||||||
### Casos Básicos
|
|
||||||
**Archivo**: `debug_templates/basic_test.json`
|
|
||||||
- Operaciones con FourBytes e IntBase
|
|
||||||
- Variables y SymPy básico
|
|
||||||
|
|
||||||
### Testing de Errores
|
|
||||||
**Archivo**: `debug_templates/error_debug.json`
|
|
||||||
- Máscaras inválidas
|
|
||||||
- IPs fuera de rango
|
|
||||||
- Expresiones malformadas
|
|
||||||
|
|
||||||
### Información de Contexto
|
|
||||||
**Archivo**: `debug_templates/context_debug.json`
|
|
||||||
- Estado completo del motor
|
|
||||||
- Tipos registrados
|
|
||||||
- Sistema de ecuaciones
|
|
||||||
|
|
||||||
### Tokenización
|
|
||||||
**Archivo**: `debug_templates/tokenization_test.json`
|
|
||||||
- Debug del sistema de parsing
|
|
||||||
- Reglas de tokenización
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Flujo de Resolución de Problemas
|
|
||||||
|
|
||||||
### 1. Identificar el Problema
|
|
||||||
- ¿Es un error de evaluación?
|
|
||||||
- ¿Es un problema de tokenización?
|
|
||||||
- ¿Es un problema de estado del motor?
|
|
||||||
|
|
||||||
### 2. Crear Query de Diagnóstico
|
|
||||||
- Usar query `input` para reproducir el problema
|
|
||||||
- Usar query `exec` para inspeccionar el estado
|
|
||||||
|
|
||||||
### 3. Analizar Resultados
|
|
||||||
- Verificar `success: true/false`
|
|
||||||
- Examinar `error` si hay fallo
|
|
||||||
- Comparar `output` (texto de la app) con `exec_result` (valor interno)
|
|
||||||
|
|
||||||
### 4. Iterar
|
|
||||||
- Crear nuevas queries basadas en hallazgos
|
|
||||||
- Profundizar en áreas problemáticas
|
|
||||||
- Verificar soluciones con queries adicionales
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Ejemplo Completo de Debugging
|
|
||||||
|
|
||||||
**Problema**: "La operación `192.168.1.x + 1` no funciona correctamente"
|
|
||||||
|
|
||||||
### Paso 1: Crear archivo de debug
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"queries": [
|
|
||||||
{"index": 0, "type": "input", "content": "192.168.1.x + 1"},
|
|
||||||
{"index": 1, "type": "exec", "content": "type(engine.last_result).__name__"},
|
|
||||||
{"index": 2, "type": "exec", "content": "engine.last_result.has_symbols"},
|
|
||||||
{"index": 3, "type": "exec", "content": "engine.parser.process_expression('192.168.1.x + 1')"},
|
|
||||||
{"index": 4, "type": "input", "content": "ip = 192.168.1.x"},
|
|
||||||
{"index": 5, "type": "exec", "content": "type(engine.symbol_table['ip'])"},
|
|
||||||
{"index": 6, "type": "input", "content": "ip.substitute(x=5)"}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Paso 2: Ejecutar
|
|
||||||
```bash
|
|
||||||
python simple_debug.py debug_problema.json
|
|
||||||
```
|
|
||||||
|
|
||||||
### Paso 3: Analizar resultados
|
|
||||||
- Verificar si `192.168.1.x + 1` se evalúa correctamente (campo `output`)
|
|
||||||
- Comprobar el tipo resultante con `exec`
|
|
||||||
- Verificar si tiene símbolos
|
|
||||||
- Examinar cómo se tokeniza la expresión
|
|
||||||
- Probar operaciones relacionadas
|
|
||||||
|
|
||||||
Este flujo te permite identificar exactamente dónde está el problema y verificar la solución.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Consejos para LLMs
|
|
||||||
|
|
||||||
1. **Siempre usa índices secuenciales** en las queries para facilitar la lectura
|
|
||||||
2. **Combina queries `input` y `exec`** para obtener contexto completo
|
|
||||||
3. **El campo `output` es texto tal como se muestra en la aplicación**
|
|
||||||
4. **El campo `exec_result` es el valor directo de la evaluación Python**
|
|
||||||
5. **Usa los templates existentes** como punto de partida
|
|
||||||
6. **Examina `success` y `error`** antes de analizar resultados
|
|
||||||
7. **Crea queries incrementales** que construyan sobre resultados anteriores
|
|
||||||
8. **NO intentes duplicar lógica de la aplicación** - usa solo llamadas directas
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Referencia Rápida
|
|
||||||
|
|
||||||
### Query Básica
|
|
||||||
```json
|
|
||||||
{"index": N, "type": "input|exec", "content": "CONTENIDO"}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Comandos Esenciales
|
|
||||||
```bash
|
|
||||||
python simple_debug.py archivo.json # Ejecutar debug
|
|
||||||
python simple_debug.py archivo.json --verbose # Con detalles
|
|
||||||
python simple_debug.py archivo.json -o resultado.json # Salida específica
|
|
||||||
```
|
|
||||||
|
|
||||||
### Inspección Básica del Motor
|
|
||||||
```python
|
|
||||||
"engine.last_result" # Último resultado
|
|
||||||
"type(engine.last_result)" # Tipo del resultado
|
|
||||||
"engine.symbol_table" # Variables actuales
|
|
||||||
"engine.get_available_types()" # Tipos registrados
|
|
||||||
"engine.parser.get_tokenization_info()" # Info de parsing
|
|
||||||
```
|
|
||||||
|
|
||||||
### Análisis de Resultado
|
|
||||||
```python
|
|
||||||
"success": true/false # ¿Éxito?
|
|
||||||
"error": "mensaje" # Error si falla
|
|
||||||
"output": "resultado" # Texto tal como se muestra en la app
|
|
||||||
"exec_result": valor # Valor directo (exec queries)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Templates Disponibles
|
|
||||||
- `debug_templates/basic_test.json` - Pruebas básicas
|
|
||||||
- `debug_templates/error_debug.json` - Testing de errores
|
|
||||||
- `debug_templates/context_debug.json` - Estado del motor
|
|
||||||
- `debug_templates/tokenization_test.json` - Debug de parsing
|
|
||||||
|
|
||||||
### Workflow Típico
|
|
||||||
1. **Identificar problema** → Crear query `input` para reproducir
|
|
||||||
2. **Inspeccionar estado** → Añadir queries `exec` para diagnosticar
|
|
||||||
3. **Analizar resultados** → Examinar `success`, `error`, `output`
|
|
||||||
4. **Iterar** → Crear nuevas queries basadas en hallazgos
|
|
||||||
|
|
||||||
**Principio clave**: texto → texto. La API no interpreta ni procesa, solo encapsula llamadas directas al motor existente.
|
|
|
@ -1,135 +0,0 @@
|
||||||
{
|
|
||||||
"execution_info": {
|
|
||||||
"timestamp": "2025-06-05T18:02:09.698502Z",
|
|
||||||
"total_queries": 11,
|
|
||||||
"successful": 11,
|
|
||||||
"failed": 0,
|
|
||||||
"input_file": "debug_templates\\context_debug.json"
|
|
||||||
},
|
|
||||||
"results": [
|
|
||||||
{
|
|
||||||
"index": 0,
|
|
||||||
"input": "x = 5",
|
|
||||||
"output": "5",
|
|
||||||
"result_type": "Integer",
|
|
||||||
"success": true,
|
|
||||||
"error": null,
|
|
||||||
"display_class": "[Integer]"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 1,
|
|
||||||
"input": "y = x + 10",
|
|
||||||
"output": "15",
|
|
||||||
"result_type": "Integer",
|
|
||||||
"success": true,
|
|
||||||
"error": null,
|
|
||||||
"display_class": "[Integer]"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 2,
|
|
||||||
"input": "engine.symbol_table",
|
|
||||||
"output": "{'x': 5, 'y': 15}",
|
|
||||||
"result_type": "dict",
|
|
||||||
"success": true,
|
|
||||||
"error": null,
|
|
||||||
"exec_result": "{'x': 5, 'y': 15, 'z': [-sqrt(-b), sqrt(-b)]}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 3,
|
|
||||||
"input": "len(engine.equations)",
|
|
||||||
"output": "2",
|
|
||||||
"result_type": "int",
|
|
||||||
"success": true,
|
|
||||||
"error": null,
|
|
||||||
"exec_result": 2
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 4,
|
|
||||||
"input": "list(engine.base_context.keys())[:10]",
|
|
||||||
"output": "['pi', 'e', 'I', 'oo', 'sin', 'cos', 'tan', 'asin', 'acos', 'atan']",
|
|
||||||
"result_type": "list",
|
|
||||||
"success": true,
|
|
||||||
"error": null,
|
|
||||||
"exec_result": [
|
|
||||||
"pi",
|
|
||||||
"e",
|
|
||||||
"I",
|
|
||||||
"oo",
|
|
||||||
"sin",
|
|
||||||
"cos",
|
|
||||||
"tan",
|
|
||||||
"asin",
|
|
||||||
"acos",
|
|
||||||
"atan"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 5,
|
|
||||||
"input": "engine.get_available_types()",
|
|
||||||
"output": "{'registered_classes': {'Bin': <class 'bin_type.Class_Bin'>, 'Chr': <class 'chr_type.Class_Chr'>, 'Dec': <class 'dec_type.Class_Dec'>, 'FourBytes': <class 'fourbytes_type.FourBytes'>, 'Hex': <class 'hex_type.Class_Hex'>, 'IntBase': <class 'intbase_type.IntBase'>, 'IP4': <class 'ip4_type.Class_IP4'>, 'IP4Mask': <class 'ip4_type.IP4Mask'>, 'LaTeX': <class 'latex_type.Class_LaTeX'>}, 'bracket_classes': ['bin', 'intbase', 'IP4', 'chr', 'IntBase', 'ip4', 'fourbytes', 'Chr', 'dec', 'latex', 'FourBytes', 'Hex', 'LaTeX', 'Dec', 'Bin', 'IP4Mask', 'hex', 'ip4mask'], 'total_context_entries': 64, 'helper_functions_count': 9}",
|
|
||||||
"result_type": "dict",
|
|
||||||
"success": true,
|
|
||||||
"error": null,
|
|
||||||
"exec_result": "{'registered_classes': {'Bin': <class 'bin_type.Class_Bin'>, 'Chr': <class 'chr_type.Class_Chr'>, 'Dec': <class 'dec_type.Class_Dec'>, 'FourBytes': <class 'fourbytes_type.FourBytes'>, 'Hex': <class 'hex_type.Class_Hex'>, 'IntBase': <class 'intbase_type.IntBase'>, 'IP4': <class 'ip4_type.Class_IP4'>, 'IP4Mask': <class 'ip4_type.IP4Mask'>, 'LaTeX': <class 'latex_type.Class_LaTeX'>}, 'bracket_classes': ['bin', 'intbase', 'IP4', 'chr', 'IntBase', 'ip4', 'fourbytes', 'Chr', 'dec', 'latex', 'FourBytes', 'Hex', 'LaTeX', 'Dec', 'Bin', 'IP4Mask', 'hex', 'ip4mask'], 'total_context_entries': 64, 'helper_functions_count': 9}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 6,
|
|
||||||
"input": "list(engine.registered_types_info['registered_classes'].keys())",
|
|
||||||
"output": "['Bin', 'Chr', 'Dec', 'FourBytes', 'Hex', 'IntBase', 'IP4', 'IP4Mask', 'LaTeX']",
|
|
||||||
"result_type": "list",
|
|
||||||
"success": true,
|
|
||||||
"error": null,
|
|
||||||
"exec_result": [
|
|
||||||
"Bin",
|
|
||||||
"Chr",
|
|
||||||
"Dec",
|
|
||||||
"FourBytes",
|
|
||||||
"Hex",
|
|
||||||
"IntBase",
|
|
||||||
"IP4",
|
|
||||||
"IP4Mask",
|
|
||||||
"LaTeX"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 7,
|
|
||||||
"input": "engine.registered_types_info['class_count']",
|
|
||||||
"output": "9",
|
|
||||||
"result_type": "int",
|
|
||||||
"success": true,
|
|
||||||
"error": null,
|
|
||||||
"exec_result": 9
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 8,
|
|
||||||
"input": "z = solve(a**2 + b, a)",
|
|
||||||
"output": "[-sqrt(-b), sqrt(-b)]",
|
|
||||||
"result_type": "list",
|
|
||||||
"success": true,
|
|
||||||
"error": null,
|
|
||||||
"display_class": "[list]"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 9,
|
|
||||||
"input": "engine._classify_line('z = solve(a**2 + b, a)')",
|
|
||||||
"output": "assignment",
|
|
||||||
"result_type": "str",
|
|
||||||
"success": true,
|
|
||||||
"error": null,
|
|
||||||
"exec_result": "assignment"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 10,
|
|
||||||
"input": "engine._extract_variable_names('x + y + z')",
|
|
||||||
"output": "['x', 'y', 'z']",
|
|
||||||
"result_type": "list",
|
|
||||||
"success": true,
|
|
||||||
"error": null,
|
|
||||||
"exec_result": [
|
|
||||||
"x",
|
|
||||||
"y",
|
|
||||||
"z"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -14,7 +14,9 @@ class IntBase(ClassBase):
|
||||||
def __init__(self, value_str, base=10):
|
def __init__(self, value_str, base=10):
|
||||||
self.value_str = str(value_str)
|
self.value_str = str(value_str)
|
||||||
self.base = int(base)
|
self.base = int(base)
|
||||||
self.has_symbols = bool(re.search(r'[a-zA-Z_]', self.value_str))
|
|
||||||
|
# CORREGIDO: Detectar símbolos considerando la base numérica
|
||||||
|
self.has_symbols = self._has_algebraic_symbols()
|
||||||
|
|
||||||
if self.has_symbols:
|
if self.has_symbols:
|
||||||
# Modo algebraico: mantener símbolos INTERNAMENTE, no convertir a SymPy aún
|
# Modo algebraico: mantener símbolos INTERNAMENTE, no convertir a SymPy aún
|
||||||
|
@ -32,9 +34,44 @@ class IntBase(ClassBase):
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise ValueError(f"Valor inválido '{self.value_str}' para base {self.base}")
|
raise ValueError(f"Valor inválido '{self.value_str}' para base {self.base}")
|
||||||
|
|
||||||
|
def _has_algebraic_symbols(self):
|
||||||
|
"""
|
||||||
|
Detecta si hay símbolos algebraicos reales, no dígitos válidos para la base
|
||||||
|
"""
|
||||||
|
# Definir dígitos válidos según la base
|
||||||
|
if self.base <= 10:
|
||||||
|
valid_digits = set(f"0123456789"[:self.base])
|
||||||
|
else:
|
||||||
|
# Para bases > 10, usar 0-9 y A-Z hasta la base
|
||||||
|
valid_digits = set("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[:self.base])
|
||||||
|
valid_digits.update(set("0123456789abcdefghijklmnopqrstuvwxyz"[:self.base]))
|
||||||
|
|
||||||
|
# Verificar si hay caracteres que NO son dígitos válidos para esta base
|
||||||
|
for char in self.value_str:
|
||||||
|
if char not in valid_digits and char not in '()+-*/': # Permitir operadores básicos
|
||||||
|
# Si encontramos una letra que NO es dígito válido, es un símbolo
|
||||||
|
if re.match(r'[a-zA-Z_]', char):
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
def _extract_symbols(self):
|
def _extract_symbols(self):
|
||||||
"""Extrae símbolos de la cadena, manteniendo caracteres únicos"""
|
"""Extrae símbolos algebraicos reales (no dígitos de la base)"""
|
||||||
return list(set(re.findall(r'[a-zA-Z_][a-zA-Z0-9_]*', self.value_str)))
|
# Definir dígitos válidos según la base
|
||||||
|
if self.base <= 10:
|
||||||
|
valid_digits = set(f"0123456789"[:self.base])
|
||||||
|
else:
|
||||||
|
valid_digits = set("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[:self.base])
|
||||||
|
valid_digits.update(set("0123456789abcdefghijklmnopqrstuvwxyz"[:self.base]))
|
||||||
|
|
||||||
|
symbols = []
|
||||||
|
for match in re.finditer(r'[a-zA-Z_][a-zA-Z0-9_]*', self.value_str):
|
||||||
|
symbol = match.group()
|
||||||
|
# Solo agregar si NO es completamente un dígito válido
|
||||||
|
if not all(c in valid_digits for c in symbol):
|
||||||
|
symbols.append(symbol)
|
||||||
|
|
||||||
|
return list(set(symbols))
|
||||||
|
|
||||||
def substitute(self, **kwargs):
|
def substitute(self, **kwargs):
|
||||||
"""Sustitución NATIVA - mantiene como IntBase"""
|
"""Sustitución NATIVA - mantiene como IntBase"""
|
||||||
|
|
|
@ -1,569 +0,0 @@
|
||||||
{
|
|
||||||
"execution_info": {
|
|
||||||
"timestamp": "2025-06-05T18:11:38.337776Z",
|
|
||||||
"total_queries": 12,
|
|
||||||
"successful": 12,
|
|
||||||
"failed": 0,
|
|
||||||
"input_file": "debug_templates\\display_format_test.json"
|
|
||||||
},
|
|
||||||
"results": [
|
|
||||||
{
|
|
||||||
"index": 0,
|
|
||||||
"input": "192.168.1.1 + 1",
|
|
||||||
"output": "192.168.1.2",
|
|
||||||
"result_type": "FourBytes",
|
|
||||||
"success": true,
|
|
||||||
"error": null,
|
|
||||||
"output_raw": {
|
|
||||||
"parts": [
|
|
||||||
[
|
|
||||||
"custom_type",
|
|
||||||
"192.168.1.2"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"class_hint",
|
|
||||||
"[FourBytes]"
|
|
||||||
]
|
|
||||||
],
|
|
||||||
"formatted_text": "[custom_type]192.168.1.2[class_hint][FourBytes]",
|
|
||||||
"tag_info": {
|
|
||||||
"error": {
|
|
||||||
"fg": "#ff6b6b",
|
|
||||||
"font": "bold"
|
|
||||||
},
|
|
||||||
"result": {
|
|
||||||
"fg": "#abdbe3"
|
|
||||||
},
|
|
||||||
"symbolic": {
|
|
||||||
"fg": "#82aaff"
|
|
||||||
},
|
|
||||||
"numeric": {
|
|
||||||
"fg": "#c3e88d"
|
|
||||||
},
|
|
||||||
"equation": {
|
|
||||||
"fg": "#c792ea"
|
|
||||||
},
|
|
||||||
"info": {
|
|
||||||
"fg": "#ffcb6b"
|
|
||||||
},
|
|
||||||
"comment": {
|
|
||||||
"fg": "#546e7a"
|
|
||||||
},
|
|
||||||
"class_hint": {
|
|
||||||
"fg": "#888888"
|
|
||||||
},
|
|
||||||
"type_hint": {
|
|
||||||
"fg": "#6a6a6a"
|
|
||||||
},
|
|
||||||
"custom_type": {
|
|
||||||
"fg": "#f9a825"
|
|
||||||
},
|
|
||||||
"hex": {
|
|
||||||
"fg": "#f9a825"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"fg": "#4fc3f7"
|
|
||||||
},
|
|
||||||
"ip": {
|
|
||||||
"fg": "#fff176"
|
|
||||||
},
|
|
||||||
"date": {
|
|
||||||
"fg": "#ff8a80"
|
|
||||||
},
|
|
||||||
"chr_type": {
|
|
||||||
"fg": "#80cbc4"
|
|
||||||
},
|
|
||||||
"helper": {
|
|
||||||
"fg": "#ffd700",
|
|
||||||
"font": "italic"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"display_class": "[FourBytes]"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 1,
|
|
||||||
"input": "engine.last_result",
|
|
||||||
"output": "192.168.1.2",
|
|
||||||
"result_type": "FourBytes",
|
|
||||||
"success": true,
|
|
||||||
"error": null,
|
|
||||||
"exec_result": "192.168.1.2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 2,
|
|
||||||
"input": "16#FF00",
|
|
||||||
"output": "16#FF00",
|
|
||||||
"result_type": "IntBase",
|
|
||||||
"success": true,
|
|
||||||
"error": null,
|
|
||||||
"output_raw": {
|
|
||||||
"parts": [
|
|
||||||
[
|
|
||||||
"custom_type",
|
|
||||||
"16#FF00"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"class_hint",
|
|
||||||
"[IntBase]"
|
|
||||||
]
|
|
||||||
],
|
|
||||||
"formatted_text": "[custom_type]16#FF00[class_hint][IntBase]",
|
|
||||||
"tag_info": {
|
|
||||||
"error": {
|
|
||||||
"fg": "#ff6b6b",
|
|
||||||
"font": "bold"
|
|
||||||
},
|
|
||||||
"result": {
|
|
||||||
"fg": "#abdbe3"
|
|
||||||
},
|
|
||||||
"symbolic": {
|
|
||||||
"fg": "#82aaff"
|
|
||||||
},
|
|
||||||
"numeric": {
|
|
||||||
"fg": "#c3e88d"
|
|
||||||
},
|
|
||||||
"equation": {
|
|
||||||
"fg": "#c792ea"
|
|
||||||
},
|
|
||||||
"info": {
|
|
||||||
"fg": "#ffcb6b"
|
|
||||||
},
|
|
||||||
"comment": {
|
|
||||||
"fg": "#546e7a"
|
|
||||||
},
|
|
||||||
"class_hint": {
|
|
||||||
"fg": "#888888"
|
|
||||||
},
|
|
||||||
"type_hint": {
|
|
||||||
"fg": "#6a6a6a"
|
|
||||||
},
|
|
||||||
"custom_type": {
|
|
||||||
"fg": "#f9a825"
|
|
||||||
},
|
|
||||||
"hex": {
|
|
||||||
"fg": "#f9a825"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"fg": "#4fc3f7"
|
|
||||||
},
|
|
||||||
"ip": {
|
|
||||||
"fg": "#fff176"
|
|
||||||
},
|
|
||||||
"date": {
|
|
||||||
"fg": "#ff8a80"
|
|
||||||
},
|
|
||||||
"chr_type": {
|
|
||||||
"fg": "#80cbc4"
|
|
||||||
},
|
|
||||||
"helper": {
|
|
||||||
"fg": "#ffd700",
|
|
||||||
"font": "italic"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"display_class": "[IntBase]"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 3,
|
|
||||||
"input": "engine.last_result.base",
|
|
||||||
"output": "16",
|
|
||||||
"result_type": "int",
|
|
||||||
"success": true,
|
|
||||||
"error": null,
|
|
||||||
"exec_result": 16
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 4,
|
|
||||||
"input": "x = solve(a**2 - 4, a)",
|
|
||||||
"output": "[-2, 2]",
|
|
||||||
"result_type": "list",
|
|
||||||
"success": true,
|
|
||||||
"error": null,
|
|
||||||
"output_raw": {
|
|
||||||
"parts": [
|
|
||||||
[
|
|
||||||
"info",
|
|
||||||
"x = [-2, 2]"
|
|
||||||
]
|
|
||||||
],
|
|
||||||
"formatted_text": "[info]x = [-2, 2]",
|
|
||||||
"tag_info": {
|
|
||||||
"error": {
|
|
||||||
"fg": "#ff6b6b",
|
|
||||||
"font": "bold"
|
|
||||||
},
|
|
||||||
"result": {
|
|
||||||
"fg": "#abdbe3"
|
|
||||||
},
|
|
||||||
"symbolic": {
|
|
||||||
"fg": "#82aaff"
|
|
||||||
},
|
|
||||||
"numeric": {
|
|
||||||
"fg": "#c3e88d"
|
|
||||||
},
|
|
||||||
"equation": {
|
|
||||||
"fg": "#c792ea"
|
|
||||||
},
|
|
||||||
"info": {
|
|
||||||
"fg": "#ffcb6b"
|
|
||||||
},
|
|
||||||
"comment": {
|
|
||||||
"fg": "#546e7a"
|
|
||||||
},
|
|
||||||
"class_hint": {
|
|
||||||
"fg": "#888888"
|
|
||||||
},
|
|
||||||
"type_hint": {
|
|
||||||
"fg": "#6a6a6a"
|
|
||||||
},
|
|
||||||
"custom_type": {
|
|
||||||
"fg": "#f9a825"
|
|
||||||
},
|
|
||||||
"hex": {
|
|
||||||
"fg": "#f9a825"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"fg": "#4fc3f7"
|
|
||||||
},
|
|
||||||
"ip": {
|
|
||||||
"fg": "#fff176"
|
|
||||||
},
|
|
||||||
"date": {
|
|
||||||
"fg": "#ff8a80"
|
|
||||||
},
|
|
||||||
"chr_type": {
|
|
||||||
"fg": "#80cbc4"
|
|
||||||
},
|
|
||||||
"helper": {
|
|
||||||
"fg": "#ffd700",
|
|
||||||
"font": "italic"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"display_class": "[list]"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 5,
|
|
||||||
"input": "type(engine.symbol_table['x'])",
|
|
||||||
"output": "<class 'list'>",
|
|
||||||
"result_type": "type",
|
|
||||||
"success": true,
|
|
||||||
"error": null,
|
|
||||||
"exec_result": "<class 'list'>"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 6,
|
|
||||||
"input": "IP4Mask(255.255.255.0)",
|
|
||||||
"output": "255.255.255.0",
|
|
||||||
"result_type": "IP4Mask",
|
|
||||||
"success": true,
|
|
||||||
"error": null,
|
|
||||||
"output_raw": {
|
|
||||||
"parts": [
|
|
||||||
[
|
|
||||||
"custom_type",
|
|
||||||
"255.255.255.0"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"class_hint",
|
|
||||||
"[IP4Mask]"
|
|
||||||
]
|
|
||||||
],
|
|
||||||
"formatted_text": "[custom_type]255.255.255.0[class_hint][IP4Mask]",
|
|
||||||
"tag_info": {
|
|
||||||
"error": {
|
|
||||||
"fg": "#ff6b6b",
|
|
||||||
"font": "bold"
|
|
||||||
},
|
|
||||||
"result": {
|
|
||||||
"fg": "#abdbe3"
|
|
||||||
},
|
|
||||||
"symbolic": {
|
|
||||||
"fg": "#82aaff"
|
|
||||||
},
|
|
||||||
"numeric": {
|
|
||||||
"fg": "#c3e88d"
|
|
||||||
},
|
|
||||||
"equation": {
|
|
||||||
"fg": "#c792ea"
|
|
||||||
},
|
|
||||||
"info": {
|
|
||||||
"fg": "#ffcb6b"
|
|
||||||
},
|
|
||||||
"comment": {
|
|
||||||
"fg": "#546e7a"
|
|
||||||
},
|
|
||||||
"class_hint": {
|
|
||||||
"fg": "#888888"
|
|
||||||
},
|
|
||||||
"type_hint": {
|
|
||||||
"fg": "#6a6a6a"
|
|
||||||
},
|
|
||||||
"custom_type": {
|
|
||||||
"fg": "#f9a825"
|
|
||||||
},
|
|
||||||
"hex": {
|
|
||||||
"fg": "#f9a825"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"fg": "#4fc3f7"
|
|
||||||
},
|
|
||||||
"ip": {
|
|
||||||
"fg": "#fff176"
|
|
||||||
},
|
|
||||||
"date": {
|
|
||||||
"fg": "#ff8a80"
|
|
||||||
},
|
|
||||||
"chr_type": {
|
|
||||||
"fg": "#80cbc4"
|
|
||||||
},
|
|
||||||
"helper": {
|
|
||||||
"fg": "#ffd700",
|
|
||||||
"font": "italic"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"display_class": "[IP4Mask]"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 7,
|
|
||||||
"input": "engine.last_result.get_prefix_int()",
|
|
||||||
"output": "24",
|
|
||||||
"result_type": "int",
|
|
||||||
"success": true,
|
|
||||||
"error": null,
|
|
||||||
"exec_result": 24
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 8,
|
|
||||||
"input": "# Este es un comentario",
|
|
||||||
"output": "None",
|
|
||||||
"result_type": "NoneType",
|
|
||||||
"success": true,
|
|
||||||
"error": null,
|
|
||||||
"output_raw": {
|
|
||||||
"parts": [
|
|
||||||
[
|
|
||||||
"comment",
|
|
||||||
"# Este es un comentario"
|
|
||||||
]
|
|
||||||
],
|
|
||||||
"formatted_text": "[comment]# Este es un comentario",
|
|
||||||
"tag_info": {
|
|
||||||
"error": {
|
|
||||||
"fg": "#ff6b6b",
|
|
||||||
"font": "bold"
|
|
||||||
},
|
|
||||||
"result": {
|
|
||||||
"fg": "#abdbe3"
|
|
||||||
},
|
|
||||||
"symbolic": {
|
|
||||||
"fg": "#82aaff"
|
|
||||||
},
|
|
||||||
"numeric": {
|
|
||||||
"fg": "#c3e88d"
|
|
||||||
},
|
|
||||||
"equation": {
|
|
||||||
"fg": "#c792ea"
|
|
||||||
},
|
|
||||||
"info": {
|
|
||||||
"fg": "#ffcb6b"
|
|
||||||
},
|
|
||||||
"comment": {
|
|
||||||
"fg": "#546e7a"
|
|
||||||
},
|
|
||||||
"class_hint": {
|
|
||||||
"fg": "#888888"
|
|
||||||
},
|
|
||||||
"type_hint": {
|
|
||||||
"fg": "#6a6a6a"
|
|
||||||
},
|
|
||||||
"custom_type": {
|
|
||||||
"fg": "#f9a825"
|
|
||||||
},
|
|
||||||
"hex": {
|
|
||||||
"fg": "#f9a825"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"fg": "#4fc3f7"
|
|
||||||
},
|
|
||||||
"ip": {
|
|
||||||
"fg": "#fff176"
|
|
||||||
},
|
|
||||||
"date": {
|
|
||||||
"fg": "#ff8a80"
|
|
||||||
},
|
|
||||||
"chr_type": {
|
|
||||||
"fg": "#80cbc4"
|
|
||||||
},
|
|
||||||
"helper": {
|
|
||||||
"fg": "#ffd700",
|
|
||||||
"font": "italic"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"display_class": "[NoneType]"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 9,
|
|
||||||
"input": "invalid_expression",
|
|
||||||
"output": "invalid_expression",
|
|
||||||
"result_type": "Symbol",
|
|
||||||
"success": true,
|
|
||||||
"error": null,
|
|
||||||
"output_raw": {
|
|
||||||
"parts": [
|
|
||||||
[
|
|
||||||
"symbolic",
|
|
||||||
"invalid_expression"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"class_hint",
|
|
||||||
"[Sympy]"
|
|
||||||
]
|
|
||||||
],
|
|
||||||
"formatted_text": "[symbolic]invalid_expression[class_hint][Sympy]",
|
|
||||||
"tag_info": {
|
|
||||||
"error": {
|
|
||||||
"fg": "#ff6b6b",
|
|
||||||
"font": "bold"
|
|
||||||
},
|
|
||||||
"result": {
|
|
||||||
"fg": "#abdbe3"
|
|
||||||
},
|
|
||||||
"symbolic": {
|
|
||||||
"fg": "#82aaff"
|
|
||||||
},
|
|
||||||
"numeric": {
|
|
||||||
"fg": "#c3e88d"
|
|
||||||
},
|
|
||||||
"equation": {
|
|
||||||
"fg": "#c792ea"
|
|
||||||
},
|
|
||||||
"info": {
|
|
||||||
"fg": "#ffcb6b"
|
|
||||||
},
|
|
||||||
"comment": {
|
|
||||||
"fg": "#546e7a"
|
|
||||||
},
|
|
||||||
"class_hint": {
|
|
||||||
"fg": "#888888"
|
|
||||||
},
|
|
||||||
"type_hint": {
|
|
||||||
"fg": "#6a6a6a"
|
|
||||||
},
|
|
||||||
"custom_type": {
|
|
||||||
"fg": "#f9a825"
|
|
||||||
},
|
|
||||||
"hex": {
|
|
||||||
"fg": "#f9a825"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"fg": "#4fc3f7"
|
|
||||||
},
|
|
||||||
"ip": {
|
|
||||||
"fg": "#fff176"
|
|
||||||
},
|
|
||||||
"date": {
|
|
||||||
"fg": "#ff8a80"
|
|
||||||
},
|
|
||||||
"chr_type": {
|
|
||||||
"fg": "#80cbc4"
|
|
||||||
},
|
|
||||||
"helper": {
|
|
||||||
"fg": "#ffd700",
|
|
||||||
"font": "italic"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"display_class": "[Symbol]"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 10,
|
|
||||||
"input": "matriz = Matrix([[1, 2], [3, 4]])",
|
|
||||||
"output": "Matrix([[1, 2], [3, 4]])",
|
|
||||||
"result_type": "MutableDenseMatrix",
|
|
||||||
"success": true,
|
|
||||||
"error": null,
|
|
||||||
"output_raw": {
|
|
||||||
"parts": [
|
|
||||||
[
|
|
||||||
"info",
|
|
||||||
"matriz = Matrix([[1, 2], [3, 4]])"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"numeric",
|
|
||||||
"≈ Matrix([[1.00000000000000, 2.00000000000000], [3.00000000000000, 4.00000000000000]])"
|
|
||||||
]
|
|
||||||
],
|
|
||||||
"formatted_text": "[info]matriz = Matrix([[1, 2], [3, 4]]) [numeric]≈ Matrix([[1.00000000000000, 2.00000000000000], [3.00000000000000, 4.00000000000000]])",
|
|
||||||
"tag_info": {
|
|
||||||
"error": {
|
|
||||||
"fg": "#ff6b6b",
|
|
||||||
"font": "bold"
|
|
||||||
},
|
|
||||||
"result": {
|
|
||||||
"fg": "#abdbe3"
|
|
||||||
},
|
|
||||||
"symbolic": {
|
|
||||||
"fg": "#82aaff"
|
|
||||||
},
|
|
||||||
"numeric": {
|
|
||||||
"fg": "#c3e88d"
|
|
||||||
},
|
|
||||||
"equation": {
|
|
||||||
"fg": "#c792ea"
|
|
||||||
},
|
|
||||||
"info": {
|
|
||||||
"fg": "#ffcb6b"
|
|
||||||
},
|
|
||||||
"comment": {
|
|
||||||
"fg": "#546e7a"
|
|
||||||
},
|
|
||||||
"class_hint": {
|
|
||||||
"fg": "#888888"
|
|
||||||
},
|
|
||||||
"type_hint": {
|
|
||||||
"fg": "#6a6a6a"
|
|
||||||
},
|
|
||||||
"custom_type": {
|
|
||||||
"fg": "#f9a825"
|
|
||||||
},
|
|
||||||
"hex": {
|
|
||||||
"fg": "#f9a825"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"fg": "#4fc3f7"
|
|
||||||
},
|
|
||||||
"ip": {
|
|
||||||
"fg": "#fff176"
|
|
||||||
},
|
|
||||||
"date": {
|
|
||||||
"fg": "#ff8a80"
|
|
||||||
},
|
|
||||||
"chr_type": {
|
|
||||||
"fg": "#80cbc4"
|
|
||||||
},
|
|
||||||
"helper": {
|
|
||||||
"fg": "#ffd700",
|
|
||||||
"font": "italic"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"display_class": "[MutableDenseMatrix]"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 11,
|
|
||||||
"input": "engine.symbol_table['matriz'].shape",
|
|
||||||
"output": "(2, 2)",
|
|
||||||
"result_type": "tuple",
|
|
||||||
"success": true,
|
|
||||||
"error": null,
|
|
||||||
"exec_result": [
|
|
||||||
2,
|
|
||||||
2
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,107 +0,0 @@
|
||||||
{
|
|
||||||
"execution_info": {
|
|
||||||
"timestamp": "2025-06-05T18:27:08.607608Z",
|
|
||||||
"total_queries": 11,
|
|
||||||
"successful": 9,
|
|
||||||
"failed": 2,
|
|
||||||
"input_file": "debug_templates\\error_debug.json"
|
|
||||||
},
|
|
||||||
"results": [
|
|
||||||
{
|
|
||||||
"index": 0,
|
|
||||||
"input": "bad_mask = 255.240.0.3",
|
|
||||||
"output": "255.240.0.3",
|
|
||||||
"result_type": "FourBytes",
|
|
||||||
"success": true,
|
|
||||||
"error": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 1,
|
|
||||||
"input": "IP4Mask(bad_mask)",
|
|
||||||
"output": "None",
|
|
||||||
"result_type": "NoneType",
|
|
||||||
"success": false,
|
|
||||||
"error": "\n❌ Máscara inválida: 255.240.0.3 (0xFFF00003)\n\n🔍 Análisis binario: 11111111.11110000.00000000.00000011\n Los bits deben ser contiguos: todos los 1s seguidos de todos los 0s\n\n✅ Ejemplos de máscaras válidas:\n /24 → 255.255.255.0 (11111111.11111111.11111111.00000000)\n /20 → 255.240.0.0 (11111111.11110000.00000000.00000000)\n /16 → 255.255.0.0 (11111111.11111111.00000000.00000000)\n /12 → 255.240.0.0 (11111111.11110000.00000000.00000000)\n\n💡 ¿Quizás querías usar 255.240.0.0 en lugar de 255.240.0.3?\n"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 2,
|
|
||||||
"input": "engine.last_result",
|
|
||||||
"output": "None",
|
|
||||||
"result_type": "NoneType",
|
|
||||||
"success": true,
|
|
||||||
"error": null,
|
|
||||||
"exec_result": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 3,
|
|
||||||
"input": "invalid_ip = 300.1.1.1",
|
|
||||||
"output": "None",
|
|
||||||
"result_type": "NoneType",
|
|
||||||
"success": false,
|
|
||||||
"error": "Error en asignación: Elemento inválido: '300'"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 4,
|
|
||||||
"input": "hasattr(engine, 'last_error')",
|
|
||||||
"output": "False",
|
|
||||||
"result_type": "bool",
|
|
||||||
"success": true,
|
|
||||||
"error": null,
|
|
||||||
"exec_result": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 5,
|
|
||||||
"input": "16#GG",
|
|
||||||
"output": "16",
|
|
||||||
"result_type": "Integer",
|
|
||||||
"success": true,
|
|
||||||
"error": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 6,
|
|
||||||
"input": "engine.debug",
|
|
||||||
"output": "False",
|
|
||||||
"result_type": "bool",
|
|
||||||
"success": true,
|
|
||||||
"error": null,
|
|
||||||
"exec_result": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 7,
|
|
||||||
"input": "divide_by_zero = 10/0",
|
|
||||||
"output": "zoo",
|
|
||||||
"result_type": "ComplexInfinity",
|
|
||||||
"success": true,
|
|
||||||
"error": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 8,
|
|
||||||
"input": "engine.symbolic_mode",
|
|
||||||
"output": "True",
|
|
||||||
"result_type": "bool",
|
|
||||||
"success": true,
|
|
||||||
"error": null,
|
|
||||||
"exec_result": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 9,
|
|
||||||
"input": "undefined_var + 5",
|
|
||||||
"output": "undefined_var + 5",
|
|
||||||
"result_type": "Add",
|
|
||||||
"success": true,
|
|
||||||
"error": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 10,
|
|
||||||
"input": "list(engine.symbol_table.keys())",
|
|
||||||
"output": "['bad_mask', 'divide_by_zero']",
|
|
||||||
"result_type": "list",
|
|
||||||
"success": true,
|
|
||||||
"error": null,
|
|
||||||
"exec_result": [
|
|
||||||
"bad_mask",
|
|
||||||
"divide_by_zero"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,491 +0,0 @@
|
||||||
{
|
|
||||||
"execution_info": {
|
|
||||||
"timestamp": "2025-06-05T18:11:18.061505Z",
|
|
||||||
"total_queries": 11,
|
|
||||||
"successful": 9,
|
|
||||||
"failed": 2,
|
|
||||||
"input_file": "debug_templates\\error_debug.json"
|
|
||||||
},
|
|
||||||
"results": [
|
|
||||||
{
|
|
||||||
"index": 0,
|
|
||||||
"input": "bad_mask = 255.240.0.3",
|
|
||||||
"output": "255.240.0.3",
|
|
||||||
"result_type": "FourBytes",
|
|
||||||
"success": true,
|
|
||||||
"error": null,
|
|
||||||
"output_raw": {
|
|
||||||
"parts": [
|
|
||||||
[
|
|
||||||
"info",
|
|
||||||
"bad_mask = 255.240.0.3"
|
|
||||||
]
|
|
||||||
],
|
|
||||||
"formatted_text": "[info]bad_mask = 255.240.0.3",
|
|
||||||
"tag_info": {
|
|
||||||
"error": {
|
|
||||||
"fg": "#ff6b6b",
|
|
||||||
"font": "bold"
|
|
||||||
},
|
|
||||||
"result": {
|
|
||||||
"fg": "#abdbe3"
|
|
||||||
},
|
|
||||||
"symbolic": {
|
|
||||||
"fg": "#82aaff"
|
|
||||||
},
|
|
||||||
"numeric": {
|
|
||||||
"fg": "#c3e88d"
|
|
||||||
},
|
|
||||||
"equation": {
|
|
||||||
"fg": "#c792ea"
|
|
||||||
},
|
|
||||||
"info": {
|
|
||||||
"fg": "#ffcb6b"
|
|
||||||
},
|
|
||||||
"comment": {
|
|
||||||
"fg": "#546e7a"
|
|
||||||
},
|
|
||||||
"class_hint": {
|
|
||||||
"fg": "#888888"
|
|
||||||
},
|
|
||||||
"type_hint": {
|
|
||||||
"fg": "#6a6a6a"
|
|
||||||
},
|
|
||||||
"custom_type": {
|
|
||||||
"fg": "#f9a825"
|
|
||||||
},
|
|
||||||
"hex": {
|
|
||||||
"fg": "#f9a825"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"fg": "#4fc3f7"
|
|
||||||
},
|
|
||||||
"ip": {
|
|
||||||
"fg": "#fff176"
|
|
||||||
},
|
|
||||||
"date": {
|
|
||||||
"fg": "#ff8a80"
|
|
||||||
},
|
|
||||||
"chr_type": {
|
|
||||||
"fg": "#80cbc4"
|
|
||||||
},
|
|
||||||
"helper": {
|
|
||||||
"fg": "#ffd700",
|
|
||||||
"font": "italic"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"display_class": "[FourBytes]"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 1,
|
|
||||||
"input": "IP4Mask(bad_mask)",
|
|
||||||
"output": "None",
|
|
||||||
"result_type": "NoneType",
|
|
||||||
"success": false,
|
|
||||||
"error": "\n❌ Máscara inválida: 255.240.0.3 (0xFFF00003)\n\n🔍 Análisis binario: 11111111.11110000.00000000.00000011\n Los bits deben ser contiguos: todos los 1s seguidos de todos los 0s\n\n✅ Ejemplos de máscaras válidas:\n /24 → 255.255.255.0 (11111111.11111111.11111111.00000000)\n /20 → 255.240.0.0 (11111111.11110000.00000000.00000000)\n /16 → 255.255.0.0 (11111111.11111111.00000000.00000000)\n /12 → 255.240.0.0 (11111111.11110000.00000000.00000000)\n\n💡 ¿Quizás querías usar 255.240.0.0 en lugar de 255.240.0.3?\n",
|
|
||||||
"output_raw": {
|
|
||||||
"parts": [
|
|
||||||
[
|
|
||||||
"error",
|
|
||||||
"Error: \n❌ Máscara inválida: 255.240.0.3 (0xFFF00003)\n\n🔍 Análisis binario: 11111111.11110000.00000000.00000011\n Los bits deben ser contiguos: todos los 1s seguidos de todos los 0s\n\n✅ Ejemplos de máscaras válidas:\n /24 → 255.255.255.0 (11111111.11111111.11111111.00000000)\n /20 → 255.240.0.0 (11111111.11110000.00000000.00000000)\n /16 → 255.255.0.0 (11111111.11111111.00000000.00000000)\n /12 → 255.240.0.0 (11111111.11110000.00000000.00000000)\n\n💡 ¿Quizás querías usar 255.240.0.0 en lugar de 255.240.0.3?\n"
|
|
||||||
]
|
|
||||||
],
|
|
||||||
"formatted_text": "[error]Error: \n❌ Máscara inválida: 255.240.0.3 (0xFFF00003)\n\n🔍 Análisis binario: 11111111.11110000.00000000.00000011\n Los bits deben ser contiguos: todos los 1s seguidos de todos los 0s\n\n✅ Ejemplos de máscaras válidas:\n /24 → 255.255.255.0 (11111111.11111111.11111111.00000000)\n /20 → 255.240.0.0 (11111111.11110000.00000000.00000000)\n /16 → 255.255.0.0 (11111111.11111111.00000000.00000000)\n /12 → 255.240.0.0 (11111111.11110000.00000000.00000000)\n\n💡 ¿Quizás querías usar 255.240.0.0 en lugar de 255.240.0.3?\n",
|
|
||||||
"tag_info": {
|
|
||||||
"error": {
|
|
||||||
"fg": "#ff6b6b",
|
|
||||||
"font": "bold"
|
|
||||||
},
|
|
||||||
"result": {
|
|
||||||
"fg": "#abdbe3"
|
|
||||||
},
|
|
||||||
"symbolic": {
|
|
||||||
"fg": "#82aaff"
|
|
||||||
},
|
|
||||||
"numeric": {
|
|
||||||
"fg": "#c3e88d"
|
|
||||||
},
|
|
||||||
"equation": {
|
|
||||||
"fg": "#c792ea"
|
|
||||||
},
|
|
||||||
"info": {
|
|
||||||
"fg": "#ffcb6b"
|
|
||||||
},
|
|
||||||
"comment": {
|
|
||||||
"fg": "#546e7a"
|
|
||||||
},
|
|
||||||
"class_hint": {
|
|
||||||
"fg": "#888888"
|
|
||||||
},
|
|
||||||
"type_hint": {
|
|
||||||
"fg": "#6a6a6a"
|
|
||||||
},
|
|
||||||
"custom_type": {
|
|
||||||
"fg": "#f9a825"
|
|
||||||
},
|
|
||||||
"hex": {
|
|
||||||
"fg": "#f9a825"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"fg": "#4fc3f7"
|
|
||||||
},
|
|
||||||
"ip": {
|
|
||||||
"fg": "#fff176"
|
|
||||||
},
|
|
||||||
"date": {
|
|
||||||
"fg": "#ff8a80"
|
|
||||||
},
|
|
||||||
"chr_type": {
|
|
||||||
"fg": "#80cbc4"
|
|
||||||
},
|
|
||||||
"helper": {
|
|
||||||
"fg": "#ffd700",
|
|
||||||
"font": "italic"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"display_class": "[NoneType]"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 2,
|
|
||||||
"input": "engine.last_result",
|
|
||||||
"output": "None",
|
|
||||||
"result_type": "NoneType",
|
|
||||||
"success": true,
|
|
||||||
"error": null,
|
|
||||||
"exec_result": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 3,
|
|
||||||
"input": "invalid_ip = 300.1.1.1",
|
|
||||||
"output": "None",
|
|
||||||
"result_type": "NoneType",
|
|
||||||
"success": false,
|
|
||||||
"error": "Error en asignación: Elemento inválido: '300'",
|
|
||||||
"output_raw": {
|
|
||||||
"parts": [
|
|
||||||
[
|
|
||||||
"error",
|
|
||||||
"Error: Error en asignación: Elemento inválido: '300'"
|
|
||||||
]
|
|
||||||
],
|
|
||||||
"formatted_text": "[error]Error: Error en asignación: Elemento inválido: '300'",
|
|
||||||
"tag_info": {
|
|
||||||
"error": {
|
|
||||||
"fg": "#ff6b6b",
|
|
||||||
"font": "bold"
|
|
||||||
},
|
|
||||||
"result": {
|
|
||||||
"fg": "#abdbe3"
|
|
||||||
},
|
|
||||||
"symbolic": {
|
|
||||||
"fg": "#82aaff"
|
|
||||||
},
|
|
||||||
"numeric": {
|
|
||||||
"fg": "#c3e88d"
|
|
||||||
},
|
|
||||||
"equation": {
|
|
||||||
"fg": "#c792ea"
|
|
||||||
},
|
|
||||||
"info": {
|
|
||||||
"fg": "#ffcb6b"
|
|
||||||
},
|
|
||||||
"comment": {
|
|
||||||
"fg": "#546e7a"
|
|
||||||
},
|
|
||||||
"class_hint": {
|
|
||||||
"fg": "#888888"
|
|
||||||
},
|
|
||||||
"type_hint": {
|
|
||||||
"fg": "#6a6a6a"
|
|
||||||
},
|
|
||||||
"custom_type": {
|
|
||||||
"fg": "#f9a825"
|
|
||||||
},
|
|
||||||
"hex": {
|
|
||||||
"fg": "#f9a825"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"fg": "#4fc3f7"
|
|
||||||
},
|
|
||||||
"ip": {
|
|
||||||
"fg": "#fff176"
|
|
||||||
},
|
|
||||||
"date": {
|
|
||||||
"fg": "#ff8a80"
|
|
||||||
},
|
|
||||||
"chr_type": {
|
|
||||||
"fg": "#80cbc4"
|
|
||||||
},
|
|
||||||
"helper": {
|
|
||||||
"fg": "#ffd700",
|
|
||||||
"font": "italic"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"display_class": "[NoneType]"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 4,
|
|
||||||
"input": "hasattr(engine, 'last_error')",
|
|
||||||
"output": "False",
|
|
||||||
"result_type": "bool",
|
|
||||||
"success": true,
|
|
||||||
"error": null,
|
|
||||||
"exec_result": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 5,
|
|
||||||
"input": "16#GG",
|
|
||||||
"output": "16",
|
|
||||||
"result_type": "Integer",
|
|
||||||
"success": true,
|
|
||||||
"error": null,
|
|
||||||
"output_raw": {
|
|
||||||
"parts": [
|
|
||||||
[
|
|
||||||
"symbolic",
|
|
||||||
"16"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"class_hint",
|
|
||||||
"[Integer]"
|
|
||||||
]
|
|
||||||
],
|
|
||||||
"formatted_text": "[symbolic]16[class_hint][Integer]",
|
|
||||||
"tag_info": {
|
|
||||||
"error": {
|
|
||||||
"fg": "#ff6b6b",
|
|
||||||
"font": "bold"
|
|
||||||
},
|
|
||||||
"result": {
|
|
||||||
"fg": "#abdbe3"
|
|
||||||
},
|
|
||||||
"symbolic": {
|
|
||||||
"fg": "#82aaff"
|
|
||||||
},
|
|
||||||
"numeric": {
|
|
||||||
"fg": "#c3e88d"
|
|
||||||
},
|
|
||||||
"equation": {
|
|
||||||
"fg": "#c792ea"
|
|
||||||
},
|
|
||||||
"info": {
|
|
||||||
"fg": "#ffcb6b"
|
|
||||||
},
|
|
||||||
"comment": {
|
|
||||||
"fg": "#546e7a"
|
|
||||||
},
|
|
||||||
"class_hint": {
|
|
||||||
"fg": "#888888"
|
|
||||||
},
|
|
||||||
"type_hint": {
|
|
||||||
"fg": "#6a6a6a"
|
|
||||||
},
|
|
||||||
"custom_type": {
|
|
||||||
"fg": "#f9a825"
|
|
||||||
},
|
|
||||||
"hex": {
|
|
||||||
"fg": "#f9a825"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"fg": "#4fc3f7"
|
|
||||||
},
|
|
||||||
"ip": {
|
|
||||||
"fg": "#fff176"
|
|
||||||
},
|
|
||||||
"date": {
|
|
||||||
"fg": "#ff8a80"
|
|
||||||
},
|
|
||||||
"chr_type": {
|
|
||||||
"fg": "#80cbc4"
|
|
||||||
},
|
|
||||||
"helper": {
|
|
||||||
"fg": "#ffd700",
|
|
||||||
"font": "italic"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"display_class": "[Integer]"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 6,
|
|
||||||
"input": "engine.debug",
|
|
||||||
"output": "False",
|
|
||||||
"result_type": "bool",
|
|
||||||
"success": true,
|
|
||||||
"error": null,
|
|
||||||
"exec_result": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 7,
|
|
||||||
"input": "divide_by_zero = 10/0",
|
|
||||||
"output": "zoo",
|
|
||||||
"result_type": "ComplexInfinity",
|
|
||||||
"success": true,
|
|
||||||
"error": null,
|
|
||||||
"output_raw": {
|
|
||||||
"parts": [
|
|
||||||
[
|
|
||||||
"info",
|
|
||||||
"divide_by_zero = zoo"
|
|
||||||
]
|
|
||||||
],
|
|
||||||
"formatted_text": "[info]divide_by_zero = zoo",
|
|
||||||
"tag_info": {
|
|
||||||
"error": {
|
|
||||||
"fg": "#ff6b6b",
|
|
||||||
"font": "bold"
|
|
||||||
},
|
|
||||||
"result": {
|
|
||||||
"fg": "#abdbe3"
|
|
||||||
},
|
|
||||||
"symbolic": {
|
|
||||||
"fg": "#82aaff"
|
|
||||||
},
|
|
||||||
"numeric": {
|
|
||||||
"fg": "#c3e88d"
|
|
||||||
},
|
|
||||||
"equation": {
|
|
||||||
"fg": "#c792ea"
|
|
||||||
},
|
|
||||||
"info": {
|
|
||||||
"fg": "#ffcb6b"
|
|
||||||
},
|
|
||||||
"comment": {
|
|
||||||
"fg": "#546e7a"
|
|
||||||
},
|
|
||||||
"class_hint": {
|
|
||||||
"fg": "#888888"
|
|
||||||
},
|
|
||||||
"type_hint": {
|
|
||||||
"fg": "#6a6a6a"
|
|
||||||
},
|
|
||||||
"custom_type": {
|
|
||||||
"fg": "#f9a825"
|
|
||||||
},
|
|
||||||
"hex": {
|
|
||||||
"fg": "#f9a825"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"fg": "#4fc3f7"
|
|
||||||
},
|
|
||||||
"ip": {
|
|
||||||
"fg": "#fff176"
|
|
||||||
},
|
|
||||||
"date": {
|
|
||||||
"fg": "#ff8a80"
|
|
||||||
},
|
|
||||||
"chr_type": {
|
|
||||||
"fg": "#80cbc4"
|
|
||||||
},
|
|
||||||
"helper": {
|
|
||||||
"fg": "#ffd700",
|
|
||||||
"font": "italic"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"display_class": "[ComplexInfinity]"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 8,
|
|
||||||
"input": "engine.symbolic_mode",
|
|
||||||
"output": "True",
|
|
||||||
"result_type": "bool",
|
|
||||||
"success": true,
|
|
||||||
"error": null,
|
|
||||||
"exec_result": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 9,
|
|
||||||
"input": "undefined_var + 5",
|
|
||||||
"output": "undefined_var + 5",
|
|
||||||
"result_type": "Add",
|
|
||||||
"success": true,
|
|
||||||
"error": null,
|
|
||||||
"output_raw": {
|
|
||||||
"parts": [
|
|
||||||
[
|
|
||||||
"symbolic",
|
|
||||||
"undefined_var + 5"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"class_hint",
|
|
||||||
"[Sympy]"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"numeric",
|
|
||||||
"≈ undefined_var + 5.0"
|
|
||||||
]
|
|
||||||
],
|
|
||||||
"formatted_text": "[symbolic]undefined_var + 5[class_hint][Sympy] [numeric]≈ undefined_var + 5.0",
|
|
||||||
"tag_info": {
|
|
||||||
"error": {
|
|
||||||
"fg": "#ff6b6b",
|
|
||||||
"font": "bold"
|
|
||||||
},
|
|
||||||
"result": {
|
|
||||||
"fg": "#abdbe3"
|
|
||||||
},
|
|
||||||
"symbolic": {
|
|
||||||
"fg": "#82aaff"
|
|
||||||
},
|
|
||||||
"numeric": {
|
|
||||||
"fg": "#c3e88d"
|
|
||||||
},
|
|
||||||
"equation": {
|
|
||||||
"fg": "#c792ea"
|
|
||||||
},
|
|
||||||
"info": {
|
|
||||||
"fg": "#ffcb6b"
|
|
||||||
},
|
|
||||||
"comment": {
|
|
||||||
"fg": "#546e7a"
|
|
||||||
},
|
|
||||||
"class_hint": {
|
|
||||||
"fg": "#888888"
|
|
||||||
},
|
|
||||||
"type_hint": {
|
|
||||||
"fg": "#6a6a6a"
|
|
||||||
},
|
|
||||||
"custom_type": {
|
|
||||||
"fg": "#f9a825"
|
|
||||||
},
|
|
||||||
"hex": {
|
|
||||||
"fg": "#f9a825"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"fg": "#4fc3f7"
|
|
||||||
},
|
|
||||||
"ip": {
|
|
||||||
"fg": "#fff176"
|
|
||||||
},
|
|
||||||
"date": {
|
|
||||||
"fg": "#ff8a80"
|
|
||||||
},
|
|
||||||
"chr_type": {
|
|
||||||
"fg": "#80cbc4"
|
|
||||||
},
|
|
||||||
"helper": {
|
|
||||||
"fg": "#ffd700",
|
|
||||||
"font": "italic"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"display_class": "[Add]"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"index": 10,
|
|
||||||
"input": "list(engine.symbol_table.keys())",
|
|
||||||
"output": "['bad_mask', 'divide_by_zero']",
|
|
||||||
"result_type": "list",
|
|
||||||
"success": true,
|
|
||||||
"error": null,
|
|
||||||
"exec_result": [
|
|
||||||
"bad_mask",
|
|
||||||
"divide_by_zero"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,12 +1,12 @@
|
||||||
|
|
||||||
mask=255.240.0.0
|
a = x + 5
|
||||||
mask.ToHex()
|
x=?
|
||||||
ip=10.1.1.x
|
solve(x)
|
||||||
10.1.1.1 + 1
|
|
||||||
ip
|
|
||||||
|
|
||||||
IP4(10.1.1.4)
|
m=t+u * 5
|
||||||
IP4Mask(mask)
|
|
||||||
IP4Mask(255.255.0.0)
|
|
||||||
|
|
||||||
bad_mask = 255.240.0.3
|
t=4
|
||||||
|
m=3
|
||||||
|
u=?
|
||||||
|
|
||||||
|
u
|
|
@ -1,5 +1,6 @@
|
||||||
"""
|
"""
|
||||||
Motor de evaluación híbrida INTEGRADO con el sistema de auto-descubrimiento de tipos
|
Motor de evaluación híbrida INTEGRADO con el sistema de auto-descubrimiento de tipos
|
||||||
|
VERSIÓN CORREGIDA siguiendo principios de Guía_Base.md
|
||||||
"""
|
"""
|
||||||
import sympy
|
import sympy
|
||||||
from sympy import symbols, Symbol, sympify, solve, Eq, simplify
|
from sympy import symbols, Symbol, sympify, solve, Eq, simplify
|
||||||
|
@ -27,7 +28,7 @@ from tl_popup import PlotResult
|
||||||
class HybridEvaluationEngine:
|
class HybridEvaluationEngine:
|
||||||
"""
|
"""
|
||||||
Motor de evaluación híbrida que combina SymPy con clases especializadas
|
Motor de evaluación híbrida que combina SymPy con clases especializadas
|
||||||
VERSIÓN INTEGRADA con auto-descubrimiento de tipos
|
VERSIÓN CORREGIDA siguiendo principios de Guía_Base.md
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, auto_discover_types: bool = True, types_directory: str = "custom_types"):
|
def __init__(self, auto_discover_types: bool = True, types_directory: str = "custom_types"):
|
||||||
|
@ -49,9 +50,9 @@ class HybridEvaluationEngine:
|
||||||
self.registered_types_info = {}
|
self.registered_types_info = {}
|
||||||
self.helper_functions = []
|
self.helper_functions = []
|
||||||
|
|
||||||
# NUEVA CONFIGURACIÓN: Modo simbólico
|
# NUEVA CONFIGURACIÓN: Modo simbólico según Guía Base
|
||||||
self.symbolic_mode = True # Por defecto, mantener forma simbólica
|
self.symbolic_mode = True # Por defecto, mantener forma simbólica
|
||||||
self.show_numeric_approximation = True # Mostrar aproximación numérica
|
self.show_numeric_approximation = True # Mostrar aproximación numérica cuando es útil
|
||||||
self.keep_symbolic_fractions = True # Mantener fracciones como 4/5
|
self.keep_symbolic_fractions = True # Mantener fracciones como 4/5
|
||||||
self.auto_simplify = False # No simplificar automáticamente
|
self.auto_simplify = False # No simplificar automáticamente
|
||||||
|
|
||||||
|
@ -106,7 +107,7 @@ class HybridEvaluationEngine:
|
||||||
'integrate': sympy.integrate,
|
'integrate': sympy.integrate,
|
||||||
'limit': sympy.limit,
|
'limit': sympy.limit,
|
||||||
'series': sympy.series,
|
'series': sympy.series,
|
||||||
'solve': sympy.solve,
|
'solve': self._smart_solve,
|
||||||
'simplify': sympy.simplify,
|
'simplify': sympy.simplify,
|
||||||
'expand': sympy.expand,
|
'expand': sympy.expand,
|
||||||
'factor': sympy.factor,
|
'factor': sympy.factor,
|
||||||
|
@ -198,67 +199,83 @@ class HybridEvaluationEngine:
|
||||||
print("✅ Tipos recargados")
|
print("✅ Tipos recargados")
|
||||||
|
|
||||||
def get_available_types(self) -> Dict[str, Any]:
|
def get_available_types(self) -> Dict[str, Any]:
|
||||||
"""Retorna información sobre los tipos disponibles"""
|
"""Retorna información completa sobre tipos disponibles"""
|
||||||
return {
|
return self.registered_types_info
|
||||||
'registered_classes': self.registered_types_info.get('registered_classes', {}),
|
|
||||||
'bracket_classes': list(self.registered_types_info.get('bracket_classes', set())),
|
|
||||||
'total_context_entries': len(self.base_context),
|
|
||||||
'helper_functions_count': len(self.helper_functions)
|
|
||||||
}
|
|
||||||
|
|
||||||
def get_type_help(self, type_name: str) -> Optional[str]:
|
def get_type_help(self, type_name: str) -> Optional[str]:
|
||||||
"""Obtiene ayuda para un tipo específico"""
|
"""Obtiene ayuda para un tipo específico"""
|
||||||
# Buscar en clases registradas
|
# Buscar la clase en el registro
|
||||||
registered_classes = self.registered_types_info.get('registered_classes', {})
|
classes = self.registered_types_info.get('registered_classes', {})
|
||||||
if type_name in registered_classes:
|
if type_name in classes:
|
||||||
cls = registered_classes[type_name]
|
cls = classes[type_name]
|
||||||
if hasattr(cls, 'Helper'):
|
if hasattr(cls, 'Helper'):
|
||||||
return cls.Helper(type_name)
|
return cls.Helper("")
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def _create_plot_placeholder(self, *args, **kwargs):
|
def _create_plot_placeholder(self, *args, **kwargs):
|
||||||
"""Crear placeholder para plots que será manejado por resultados interactivos"""
|
"""Crea un resultado interactivo para plot"""
|
||||||
if self.debug:
|
return PlotResult("plot", args, kwargs)
|
||||||
print(f"🎯 Creando PlotResult con args: {args}, kwargs: {kwargs}")
|
|
||||||
return PlotResult('plot', args, kwargs)
|
|
||||||
|
|
||||||
def _create_plot3d_placeholder(self, *args, **kwargs):
|
def _create_plot3d_placeholder(self, *args, **kwargs):
|
||||||
"""Crear placeholder para plots 3D"""
|
"""Crea un resultado interactivo para plot3d"""
|
||||||
if self.debug:
|
return PlotResult("plot3d", args, kwargs)
|
||||||
print(f"🎯 Creando PlotResult 3D con args: {args}, kwargs: {kwargs}")
|
|
||||||
return PlotResult('plot3d', args, kwargs)
|
|
||||||
|
|
||||||
def _help_function(self, obj=None):
|
def _help_function(self, obj=None):
|
||||||
"""Función de ayuda integrada que usa el sistema de helpers"""
|
"""Función de ayuda personalizada"""
|
||||||
if obj is None:
|
if obj is None:
|
||||||
return "Ayuda disponible. Use help(función) para ayuda específica."
|
return "Ayuda general disponible. Usa help(objeto) para ayuda específica."
|
||||||
|
|
||||||
# Primero intentar con el objeto directamente
|
# Si es un tipo personalizado, buscar en helpers
|
||||||
if hasattr(obj, '__doc__') and obj.__doc__:
|
obj_type = type(obj).__name__
|
||||||
return obj.__doc__
|
|
||||||
elif hasattr(obj, 'Helper'):
|
|
||||||
return obj.Helper("")
|
|
||||||
|
|
||||||
# Luego buscar en helpers registrados
|
|
||||||
obj_name = getattr(obj, '__name__', str(obj))
|
|
||||||
for helper_func in self.helper_functions:
|
for helper_func in self.helper_functions:
|
||||||
try:
|
try:
|
||||||
help_result = helper_func(obj_name)
|
help_text = helper_func(obj_type)
|
||||||
if help_result:
|
if help_text and help_text.strip():
|
||||||
return help_result
|
return help_text
|
||||||
except:
|
except:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
return f"No hay ayuda disponible para {obj}"
|
# Fallback a ayuda de Python
|
||||||
|
import pydoc
|
||||||
|
return pydoc.render_doc(obj, renderer=pydoc.plaintext)
|
||||||
|
|
||||||
# ========== RESTO DE MÉTODOS EXISTENTES ==========
|
def _smart_solve(self, *args, **kwargs):
|
||||||
# (Los métodos de evaluación permanecen igual)
|
"""
|
||||||
|
Función solve inteligente que usa nuestro sistema de ecuaciones
|
||||||
|
cuando es apropiado, o llama a sympy.solve en otros casos
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
# Caso 1: solve(variable) → usar nuestro sistema
|
||||||
|
if len(args) == 1 and isinstance(args[0], (sympy.Symbol, str)):
|
||||||
|
var_name = str(args[0])
|
||||||
|
return self._solve_variable_in_system(var_name)
|
||||||
|
|
||||||
|
# Caso 2: solve(ecuacion, variable) → usar sympy.solve directamente
|
||||||
|
elif len(args) == 2:
|
||||||
|
return sympy.solve(*args, **kwargs)
|
||||||
|
|
||||||
|
# Caso 3: solve(lista_ecuaciones, lista_variables) → usar sympy.solve
|
||||||
|
elif len(args) >= 1 and isinstance(args[0], (list, tuple)):
|
||||||
|
return sympy.solve(*args, **kwargs)
|
||||||
|
|
||||||
|
# Caso 4: solve() sin argumentos → resolver todas las variables del sistema
|
||||||
|
elif len(args) == 0:
|
||||||
|
return self.solve_system()
|
||||||
|
|
||||||
|
# Otros casos → usar sympy.solve directamente
|
||||||
|
else:
|
||||||
|
return sympy.solve(*args, **kwargs)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
if self.debug:
|
||||||
|
print(f"⚠️ Error en _smart_solve: {e}")
|
||||||
|
# Fallback a sympy.solve
|
||||||
|
return sympy.solve(*args, **kwargs)
|
||||||
|
|
||||||
def evaluate_line(self, line: str) -> 'EvaluationResult':
|
def evaluate_line(self, line: str) -> 'EvaluationResult':
|
||||||
"""
|
"""
|
||||||
Evalúa una línea de código y retorna el resultado
|
Evalúa una línea de código y retorna el resultado
|
||||||
NUEVA LÓGICA: Priorizar asignaciones, intentar ecuaciones silenciosamente
|
VERSIÓN CORREGIDA siguiendo principios de Guía_Base.md
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
# 1. Aplicar tokenización distribuida
|
# 1. Aplicar tokenización distribuida
|
||||||
|
@ -267,27 +284,21 @@ class HybridEvaluationEngine:
|
||||||
if self.debug:
|
if self.debug:
|
||||||
print(f"Parse: '{line}' → '{parsed_line}'")
|
print(f"Parse: '{line}' → '{parsed_line}'")
|
||||||
|
|
||||||
# 2. Clasificar tipo de línea
|
# 2. NUEVA LÓGICA: Detectar atajo =?
|
||||||
line_type = self._classify_line(parsed_line)
|
if self._is_solve_shortcut(line):
|
||||||
|
return self._evaluate_solve_shortcut(line)
|
||||||
|
|
||||||
|
# 3. Clasificar tipo de línea según criterios de la Guía Base
|
||||||
|
line_type = self._classify_line(parsed_line, line)
|
||||||
|
|
||||||
if line_type == "comment":
|
if line_type == "comment":
|
||||||
return EvaluationResult(None, "comment", original_line=line)
|
return EvaluationResult(None, "comment", original_line=line)
|
||||||
elif line_type == "assignment":
|
elif line_type == "assignment":
|
||||||
# NUEVA LÓGICA: Para asignaciones, también intentar agregar como ecuación silenciosamente
|
return self._evaluate_assignment(parsed_line, line)
|
||||||
assignment_result = self._evaluate_assignment(parsed_line, line)
|
|
||||||
|
|
||||||
# Intentar agregar como ecuación silenciosamente (sin mostrar errores)
|
|
||||||
if not assignment_result.is_error:
|
|
||||||
try:
|
|
||||||
self._add_equation_silently(line)
|
|
||||||
except:
|
|
||||||
pass # Ignorar errores de ecuación
|
|
||||||
|
|
||||||
return assignment_result
|
|
||||||
elif line_type == "equation":
|
elif line_type == "equation":
|
||||||
return self._evaluate_equation_addition(parsed_line, line)
|
return self._evaluate_equation_addition(parsed_line, line)
|
||||||
|
|
||||||
# 3. Evaluación SymPy
|
# 4. Evaluación SymPy con evaluación numérica automática
|
||||||
return self._evaluate_sympy_expression(parsed_line, line_type, line)
|
return self._evaluate_sympy_expression(parsed_line, line_type, line)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
@ -297,137 +308,154 @@ class HybridEvaluationEngine:
|
||||||
original_line=line
|
original_line=line
|
||||||
)
|
)
|
||||||
|
|
||||||
def _classify_line(self, parsed_line: str) -> str:
|
def _is_solve_shortcut(self, line: str) -> bool:
|
||||||
"""Clasifica el tipo de línea después del parsing"""
|
"""Detecta el atajo variable=? según Guía Base"""
|
||||||
|
# Patrón: variable=?
|
||||||
|
pattern = r'^([a-zA-Z_][a-zA-Z0-9_]*)\s*=\s*\?\s*$'
|
||||||
|
return bool(re.match(pattern, line.strip()))
|
||||||
|
|
||||||
# Simplificado: priorizar asignaciones, ser menos estricto
|
def _evaluate_solve_shortcut(self, line: str) -> 'EvaluationResult':
|
||||||
if self._is_assignment(parsed_line):
|
"""Evalúa el atajo variable=? como solve(variable)"""
|
||||||
return "assignment"
|
try:
|
||||||
elif self._is_standalone_equation(parsed_line):
|
# Extraer variable del patrón variable=?
|
||||||
return "equation"
|
pattern = r'^([a-zA-Z_][a-zA-Z0-9_]*)\s*=\s*\?\s*$'
|
||||||
elif not parsed_line or parsed_line.strip().startswith('#'):
|
match = re.match(pattern, line.strip())
|
||||||
|
if not match:
|
||||||
|
raise ValueError("Formato inválido para =?")
|
||||||
|
|
||||||
|
var_name = match.group(1)
|
||||||
|
|
||||||
|
# Crear llamada a solve
|
||||||
|
solve_expression = f"solve({var_name})"
|
||||||
|
|
||||||
|
# Evaluar usando _solve_variable_in_system directamente
|
||||||
|
result = self._solve_variable_in_system(var_name)
|
||||||
|
|
||||||
|
return EvaluationResult(
|
||||||
|
result, "solve_result",
|
||||||
|
symbolic_result=result,
|
||||||
|
info=f"Resolviendo {var_name} en el sistema de ecuaciones",
|
||||||
|
original_line=line
|
||||||
|
)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
return EvaluationResult(
|
||||||
|
None, "error",
|
||||||
|
error=f"Error en solve shortcut: {e}",
|
||||||
|
original_line=line
|
||||||
|
)
|
||||||
|
|
||||||
|
def _classify_line(self, parsed_line: str, original_line: str) -> str:
|
||||||
|
"""
|
||||||
|
Clasifica el tipo de línea según criterios de la Guía Base
|
||||||
|
|
||||||
|
Criterios:
|
||||||
|
- Asignación: variable = expresión (solo variables simples)
|
||||||
|
- Ecuación: contiene = Y NO es asignación simple O contiene operadores de comparación
|
||||||
|
- Comentario: línea vacía o con #
|
||||||
|
- Expresión: todo lo demás
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Comentarios
|
||||||
|
if not parsed_line or parsed_line.strip().startswith('#'):
|
||||||
return "comment"
|
return "comment"
|
||||||
|
|
||||||
|
# Verificar si contiene operadores de ecuación
|
||||||
|
has_equals = '=' in parsed_line
|
||||||
|
has_comparison = any(op in parsed_line for op in ['==', '!=', '<=', '>=', '<', '>'])
|
||||||
|
|
||||||
|
if has_comparison:
|
||||||
|
return "equation"
|
||||||
|
|
||||||
|
if has_equals:
|
||||||
|
# Verificar si es asignación simple según Guía Base
|
||||||
|
if self._is_simple_assignment(parsed_line):
|
||||||
|
return "assignment"
|
||||||
else:
|
else:
|
||||||
|
# Es una ecuación (estructura algebraica en ambos lados)
|
||||||
|
return "equation"
|
||||||
|
|
||||||
return "expression"
|
return "expression"
|
||||||
|
|
||||||
def _is_assignment(self, line: str) -> bool:
|
def _is_simple_assignment(self, line: str) -> bool:
|
||||||
"""
|
"""
|
||||||
Detecta si una línea es una asignación de variable
|
Detecta asignaciones simples según Guía Base:
|
||||||
NUEVA LÓGICA: Priorizar asignaciones, ser menos estricto
|
- variable = expresión
|
||||||
|
- Solo un = (no ==, !=, etc.)
|
||||||
|
- Lado izquierdo es un identificador válido de Python
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
# Pattern: variable = expresión (que no sea comparación)
|
# Verificar que solo tiene un = y no es comparación
|
||||||
if '=' in line and not any(op in line for op in ['==', '!=', '<=', '>=']):
|
if line.count('=') != 1 or any(op in line for op in ['==', '!=', '<=', '>=']):
|
||||||
# Verificar que sea una asignación válida de Python
|
return False
|
||||||
|
|
||||||
parts = line.split('=', 1)
|
parts = line.split('=', 1)
|
||||||
if len(parts) == 2:
|
if len(parts) != 2:
|
||||||
|
return False
|
||||||
|
|
||||||
var_part = parts[0].strip()
|
var_part = parts[0].strip()
|
||||||
expr_part = parts[1].strip()
|
expr_part = parts[1].strip()
|
||||||
|
|
||||||
# Verificar que la parte izquierda sea un identificador válido
|
# Verificar que la parte izquierda sea un identificador válido
|
||||||
if re.match(r'^[a-zA-Z_][a-zA-Z0-9_]*$', var_part) and expr_part:
|
if not re.match(r'^[a-zA-Z_][a-zA-Z0-9_]*$', var_part):
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Verificar que la parte derecha no esté vacía
|
||||||
|
if not expr_part:
|
||||||
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
return False
|
|
||||||
except:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def _is_standalone_equation(self, line: str) -> bool:
|
|
||||||
"""
|
|
||||||
Determina si una línea es una ecuación standalone
|
|
||||||
NUEVA LÓGICA: Solo ecuaciones matemáticas obvias, no asignaciones
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
# Primero verificar si contiene '=' simple
|
|
||||||
if '=' not in line or any(op in line for op in ['==', '!=', '<=', '>=']):
|
|
||||||
return False
|
|
||||||
|
|
||||||
# NUEVA LÓGICA: Si ya fue clasificada como asignación, NO es ecuación
|
|
||||||
if self._is_assignment(line):
|
|
||||||
return False
|
|
||||||
|
|
||||||
# Solo considerar como ecuación si tiene estructura matemática compleja
|
|
||||||
# Por ejemplo: expressions con funciones matemáticas, símbolos algebraicos, etc.
|
|
||||||
if any(pattern in line for pattern in ['sin(', 'cos(', 'log(', 'sqrt(', 'diff(', 'integrate(']):
|
|
||||||
return True
|
|
||||||
|
|
||||||
# O si contiene múltiples variables en un formato algebraico
|
|
||||||
# Básicamente, ecuaciones que NO son asignaciones simples
|
|
||||||
return False
|
|
||||||
|
|
||||||
except:
|
except:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _evaluate_assignment(self, parsed_line: str, original_line: str) -> 'EvaluationResult':
|
def _evaluate_assignment(self, parsed_line: str, original_line: str) -> 'EvaluationResult':
|
||||||
"""Maneja la asignación de variables"""
|
"""
|
||||||
|
Evalúa asignación de variable según Guía Base
|
||||||
|
- Guarda el valor simbólico
|
||||||
|
- Si contiene variables no definidas, también agrega como ecuación implícita
|
||||||
|
- Proporciona evaluación numérica cuando es útil
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
# ARREGLO: Transformar asignación en llamada a _assign_variable
|
if '=' not in parsed_line:
|
||||||
# parsed_line es algo como: mask=FourBytes("255.240.0.3")
|
raise ValueError(f"Línea de asignación sin '=': {parsed_line}")
|
||||||
# Necesitamos convertirlo en: _assign_variable("mask", FourBytes("255.240.0.3"))
|
|
||||||
|
|
||||||
if '=' in parsed_line:
|
|
||||||
parts = parsed_line.split('=', 1)
|
parts = parsed_line.split('=', 1)
|
||||||
var_name = parts[0].strip()
|
var_name = parts[0].strip()
|
||||||
expr_part = parts[1].strip()
|
expr_part = parts[1].strip()
|
||||||
|
|
||||||
# Crear llamada a _assign_variable
|
# Evaluar la expresión en el contexto actual
|
||||||
assign_call = f'_assign_variable("{var_name}", {expr_part})'
|
result = self._eval_in_context(expr_part)
|
||||||
|
|
||||||
|
# Guardar en symbol_table
|
||||||
|
self.symbol_table[var_name] = result
|
||||||
|
self.last_result = result
|
||||||
|
|
||||||
|
# NUEVO: Si la asignación contiene símbolos no definidos, agregarla como ecuación implícita
|
||||||
|
if self._assignment_has_undefined_symbols(var_name, result):
|
||||||
|
try:
|
||||||
|
# Crear ecuación implícita: var_name = result
|
||||||
|
var_symbol = sympy.Symbol(var_name)
|
||||||
|
equation = sympy.Eq(var_symbol, result)
|
||||||
|
self.equations.append(equation)
|
||||||
|
|
||||||
if self.debug:
|
if self.debug:
|
||||||
print(f"🔧 Transformando asignación: '{parsed_line}' → '{assign_call}'")
|
print(f"🔗 Asignación con símbolos agregada como ecuación: {equation}")
|
||||||
|
|
||||||
# Ejecutar la asignación transformada
|
except Exception as eq_error:
|
||||||
result = self._eval_in_context(assign_call)
|
|
||||||
|
|
||||||
# Obtener el valor asignado
|
|
||||||
assigned_value = self.symbol_table.get(var_name)
|
|
||||||
else:
|
|
||||||
# Fallback: si no hay '=' algo está mal
|
|
||||||
raise ValueError(f"Línea de asignación sin '=': {parsed_line}")
|
|
||||||
|
|
||||||
|
|
||||||
# Generar evaluación numérica si está configurado para mostrarla
|
|
||||||
numeric_result = None
|
|
||||||
if self.show_numeric_approximation and hasattr(assigned_value, 'evalf'):
|
|
||||||
try:
|
|
||||||
numeric_eval = assigned_value.evalf()
|
|
||||||
# MEJORADO: Solo mostrar aproximación si es realmente útil
|
|
||||||
if hasattr(assigned_value, 'is_Rational') and assigned_value.is_Rational:
|
|
||||||
# Es una fracción racional, mostrar aproximación decimal
|
|
||||||
numeric_result = numeric_eval
|
|
||||||
elif hasattr(assigned_value, 'is_Integer') and assigned_value.is_Integer:
|
|
||||||
# Es un entero SymPy, no mostrar aproximación
|
|
||||||
numeric_result = None
|
|
||||||
elif hasattr(assigned_value, 'is_number') and assigned_value.is_number:
|
|
||||||
# Es un número, verificar si la aproximación es diferente significativamente
|
|
||||||
try:
|
|
||||||
if abs(float(numeric_eval) - float(assigned_value)) > 1e-10:
|
|
||||||
numeric_result = numeric_eval
|
|
||||||
except:
|
|
||||||
# Si no se puede comparar, mostrar solo si el string es diferente
|
|
||||||
if str(numeric_eval) != str(assigned_value):
|
|
||||||
numeric_result = numeric_eval
|
|
||||||
elif numeric_eval != assigned_value:
|
|
||||||
# Para otros casos, mostrar si son diferentes
|
|
||||||
try:
|
|
||||||
# Intentar comparación numérica más robusta
|
|
||||||
if abs(float(numeric_eval) - float(assigned_value)) > 1e-10:
|
|
||||||
numeric_result = numeric_eval
|
|
||||||
except:
|
|
||||||
# Si la comparación falla, asumir que son diferentes solo si el string es diferente
|
|
||||||
if str(numeric_eval) != str(assigned_value):
|
|
||||||
numeric_result = numeric_eval
|
|
||||||
except Exception as e:
|
|
||||||
if self.debug:
|
if self.debug:
|
||||||
print(f"DEBUG: Error en evaluación numérica: {e}")
|
print(f"⚠️ No se pudo agregar asignación como ecuación: {eq_error}")
|
||||||
pass
|
|
||||||
|
# Generar evaluación numérica según Guía Base
|
||||||
|
numeric_result = self._generate_numeric_approximation(result)
|
||||||
|
|
||||||
return EvaluationResult(
|
return EvaluationResult(
|
||||||
assigned_value, "assignment",
|
result, "assignment",
|
||||||
symbolic_result=result,
|
symbolic_result=result,
|
||||||
numeric_result=numeric_result,
|
numeric_result=numeric_result,
|
||||||
original_line=original_line
|
original_line=original_line
|
||||||
)
|
)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return EvaluationResult(
|
return EvaluationResult(
|
||||||
None, "error",
|
None, "error",
|
||||||
|
@ -435,16 +463,99 @@ class HybridEvaluationEngine:
|
||||||
original_line=original_line
|
original_line=original_line
|
||||||
)
|
)
|
||||||
|
|
||||||
def _evaluate_equation_addition(self, parsed_line: str, original_line: str) -> 'EvaluationResult':
|
def _assignment_has_undefined_symbols(self, var_name: str, result: Any) -> bool:
|
||||||
"""Maneja la adición de ecuaciones al sistema"""
|
"""
|
||||||
|
Determina si una asignación contiene símbolos no definidos
|
||||||
|
y por tanto debería agregarse como ecuación implícita
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
# Ejecutar _add_equation
|
# Obtener símbolos libres del resultado
|
||||||
result = self._eval_in_context(parsed_line)
|
if hasattr(result, 'free_symbols'):
|
||||||
|
free_symbols = result.free_symbols
|
||||||
|
|
||||||
|
# Verificar si hay símbolos que no están definidos en symbol_table
|
||||||
|
# (excluyendo el símbolo de la variable que se está asignando)
|
||||||
|
for symbol in free_symbols:
|
||||||
|
symbol_name = str(symbol)
|
||||||
|
if symbol_name != var_name and symbol_name not in self.symbol_table:
|
||||||
|
return True
|
||||||
|
# También verificar si el símbolo existe pero es solo un Symbol sin valor
|
||||||
|
elif symbol_name in self.symbol_table:
|
||||||
|
symbol_value = self.symbol_table[symbol_name]
|
||||||
|
if isinstance(symbol_value, sympy.Symbol) and str(symbol_value) == symbol_name:
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
if self.debug:
|
||||||
|
print(f"⚠️ Error verificando símbolos de asignación: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def _generate_numeric_approximation(self, result: Any) -> Optional[Any]:
|
||||||
|
"""
|
||||||
|
Genera aproximación numérica según Guía Base:
|
||||||
|
- Solo mostrar cuando la representación string difiere del resultado algebraico
|
||||||
|
"""
|
||||||
|
if not self.show_numeric_approximation:
|
||||||
|
return None
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Intentar evaluación numérica
|
||||||
|
if hasattr(result, 'evalf'):
|
||||||
|
numeric_eval = result.evalf()
|
||||||
|
|
||||||
|
# Solo mostrar si el string es diferente
|
||||||
|
if str(numeric_eval) != str(result):
|
||||||
|
return numeric_eval
|
||||||
|
elif hasattr(result, '__float__'):
|
||||||
|
try:
|
||||||
|
numeric_eval = float(result)
|
||||||
|
if str(numeric_eval) != str(result):
|
||||||
|
return numeric_eval
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
if self.debug:
|
||||||
|
print(f"DEBUG: Error en evaluación numérica: {e}")
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _evaluate_equation_addition(self, parsed_line: str, original_line: str) -> 'EvaluationResult':
|
||||||
|
"""
|
||||||
|
Evalúa y agrega ecuación al sistema según Guía Base
|
||||||
|
- Se agrega automáticamente al sistema de ecuaciones
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
# Detectar si es ecuación con = o con operadores de comparación
|
||||||
|
if '=' in parsed_line and '==' not in parsed_line:
|
||||||
|
# Ecuación con = → convertir a Eq()
|
||||||
|
parts = parsed_line.split('=', 1)
|
||||||
|
left_expr = parts[0].strip()
|
||||||
|
right_expr = parts[1].strip()
|
||||||
|
|
||||||
|
# Evaluar ambos lados
|
||||||
|
left_val = self._eval_in_context(left_expr)
|
||||||
|
right_val = self._eval_in_context(right_expr)
|
||||||
|
|
||||||
|
# Crear ecuación SymPy
|
||||||
|
equation = sympy.Eq(left_val, right_val)
|
||||||
|
|
||||||
|
else:
|
||||||
|
# Ecuación con operadores de comparación → evaluar directamente
|
||||||
|
equation = self._eval_in_context(parsed_line)
|
||||||
|
|
||||||
|
# Agregar al sistema
|
||||||
|
self.equations.append(equation)
|
||||||
|
|
||||||
return EvaluationResult(
|
return EvaluationResult(
|
||||||
result, "equation_added",
|
equation, "equation_added",
|
||||||
symbolic_result=f"Ecuación agregada: {original_line}",
|
symbolic_result=equation,
|
||||||
|
info=f"Ecuación agregada al sistema: {equation}",
|
||||||
original_line=original_line
|
original_line=original_line
|
||||||
)
|
)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return EvaluationResult(
|
return EvaluationResult(
|
||||||
None, "error",
|
None, "error",
|
||||||
|
@ -453,7 +564,9 @@ class HybridEvaluationEngine:
|
||||||
)
|
)
|
||||||
|
|
||||||
def _evaluate_sympy_expression(self, expression: str, parse_info: str, original_line: str) -> 'EvaluationResult':
|
def _evaluate_sympy_expression(self, expression: str, parse_info: str, original_line: str) -> 'EvaluationResult':
|
||||||
"""Evalúa una expresión usando SymPy"""
|
"""
|
||||||
|
Evalúa una expresión usando SymPy con evaluación numérica automática
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
# Evaluar en contexto SymPy
|
# Evaluar en contexto SymPy
|
||||||
result = self._eval_in_context(expression)
|
result = self._eval_in_context(expression)
|
||||||
|
@ -466,47 +579,25 @@ class HybridEvaluationEngine:
|
||||||
# Actualizar last_result
|
# Actualizar last_result
|
||||||
self.last_result = result
|
self.last_result = result
|
||||||
|
|
||||||
# Intentar evaluación numérica si está configurado para mostrarla
|
# Generar evaluación numérica automática según Guía Base
|
||||||
numeric_result = None
|
numeric_result = self._generate_numeric_approximation(result)
|
||||||
if self.show_numeric_approximation and hasattr(result, 'evalf'):
|
|
||||||
try:
|
# Determinar tipo de resultado
|
||||||
numeric_eval = result.evalf()
|
result_type = type(result).__name__
|
||||||
# MEJORADO: Solo mostrar evaluación numérica si es realmente útil
|
|
||||||
if hasattr(result, 'is_Integer') and result.is_Integer:
|
|
||||||
# Es un entero SymPy, no mostrar aproximación
|
|
||||||
numeric_result = None
|
|
||||||
elif hasattr(result, 'is_Rational') and result.is_Rational:
|
|
||||||
# Es una fracción racional, mostrar aproximación decimal
|
|
||||||
numeric_result = numeric_eval
|
|
||||||
elif hasattr(result, 'is_number') and result.is_number:
|
|
||||||
# Es un número, verificar si la aproximación es diferente significativamente
|
|
||||||
try:
|
|
||||||
if abs(float(numeric_eval) - float(result)) > 1e-10:
|
|
||||||
numeric_result = numeric_eval
|
|
||||||
except:
|
|
||||||
# Si no se puede comparar, mostrar solo si el string es diferente
|
|
||||||
if str(numeric_eval) != str(result):
|
|
||||||
numeric_result = numeric_eval
|
|
||||||
elif (str(numeric_eval) != str(result) and numeric_eval != result and
|
|
||||||
not (isinstance(result, (int, float)) or
|
|
||||||
(hasattr(result, 'is_number') and result.is_number and
|
|
||||||
hasattr(result, 'is_Integer') and result.is_Integer))):
|
|
||||||
numeric_result = numeric_eval
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
return EvaluationResult(
|
return EvaluationResult(
|
||||||
result, "expression",
|
result, result_type,
|
||||||
symbolic_result=result,
|
symbolic_result=result,
|
||||||
numeric_result=numeric_result,
|
numeric_result=numeric_result,
|
||||||
parse_info=parse_info,
|
parse_info=parse_info,
|
||||||
original_line=original_line
|
original_line=original_line
|
||||||
)
|
)
|
||||||
|
|
||||||
except NameError as e:
|
|
||||||
# Intentar crear símbolos automáticamente
|
|
||||||
return self._handle_undefined_symbols(expression, original_line, e)
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
# Manejar símbolos no definidos
|
||||||
|
if "undefined" in str(e).lower() or "not defined" in str(e).lower():
|
||||||
|
return self._handle_undefined_symbols(expression, original_line, e)
|
||||||
|
|
||||||
return EvaluationResult(
|
return EvaluationResult(
|
||||||
None, "error",
|
None, "error",
|
||||||
error=str(e),
|
error=str(e),
|
||||||
|
@ -719,12 +810,87 @@ class HybridEvaluationEngine:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def _get_full_context(self) -> Dict[str, Any]:
|
def _get_full_context(self) -> Dict[str, Any]:
|
||||||
"""Obtiene el contexto completo para evaluación"""
|
"""Obtiene el contexto completo para evaluación con sustituciones automáticas"""
|
||||||
context = self.base_context.copy()
|
context = self.base_context.copy()
|
||||||
context.update(self.symbol_table)
|
|
||||||
|
# NUEVO: Aplicar sustituciones automáticas en expresiones simbólicas
|
||||||
|
substituted_table = self._apply_automatic_substitutions()
|
||||||
|
context.update(substituted_table)
|
||||||
context['last'] = self.last_result
|
context['last'] = self.last_result
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
def _apply_automatic_substitutions(self) -> Dict[str, Any]:
|
||||||
|
"""
|
||||||
|
Aplica sustituciones automáticas a expresiones simbólicas usando valores conocidos
|
||||||
|
"""
|
||||||
|
substituted = {}
|
||||||
|
|
||||||
|
# Separar valores numéricos de expresiones simbólicas
|
||||||
|
numeric_values = {}
|
||||||
|
symbolic_expressions = {}
|
||||||
|
|
||||||
|
for var_name, value in self.symbol_table.items():
|
||||||
|
if hasattr(value, 'free_symbols') and value.free_symbols:
|
||||||
|
# Es una expresión simbólica
|
||||||
|
symbolic_expressions[var_name] = value
|
||||||
|
else:
|
||||||
|
# Es un valor numérico o constante
|
||||||
|
numeric_values[var_name] = value
|
||||||
|
substituted[var_name] = value
|
||||||
|
|
||||||
|
# Crear diccionario de sustituciones con valores numéricos
|
||||||
|
substitutions = {}
|
||||||
|
for var_name, value in numeric_values.items():
|
||||||
|
if hasattr(value, 'evalf'):
|
||||||
|
# Es un valor SymPy, conservar forma exacta para sustitución
|
||||||
|
substitutions[sympy.Symbol(var_name)] = value
|
||||||
|
elif isinstance(value, (int, float)):
|
||||||
|
# Es un valor numérico Python
|
||||||
|
substitutions[sympy.Symbol(var_name)] = value
|
||||||
|
else:
|
||||||
|
# Otros tipos, intentar convertir a SymPy
|
||||||
|
try:
|
||||||
|
substitutions[sympy.Symbol(var_name)] = sympy.sympify(value)
|
||||||
|
except:
|
||||||
|
substitutions[sympy.Symbol(var_name)] = value
|
||||||
|
|
||||||
|
# Aplicar sustituciones a expresiones simbólicas
|
||||||
|
for var_name, expr in symbolic_expressions.items():
|
||||||
|
try:
|
||||||
|
if substitutions:
|
||||||
|
# Aplicar todas las sustituciones conocidas
|
||||||
|
substituted_expr = expr.subs(substitutions)
|
||||||
|
|
||||||
|
# Si después de las sustituciones no quedan símbolos libres, evaluar numéricamente
|
||||||
|
if hasattr(substituted_expr, 'free_symbols') and not substituted_expr.free_symbols:
|
||||||
|
try:
|
||||||
|
# Evaluar completamente la expresión
|
||||||
|
evaluated = substituted_expr.evalf() if hasattr(substituted_expr, 'evalf') else substituted_expr
|
||||||
|
substituted[var_name] = evaluated
|
||||||
|
|
||||||
|
if self.debug:
|
||||||
|
print(f"🔄 Sustitución automática: {var_name} = {expr} → {evaluated}")
|
||||||
|
except:
|
||||||
|
# Si falla la evaluación, usar la expresión sustituida
|
||||||
|
substituted[var_name] = substituted_expr
|
||||||
|
else:
|
||||||
|
# Aún hay símbolos libres, usar expresión parcialmente sustituida
|
||||||
|
substituted[var_name] = substituted_expr
|
||||||
|
|
||||||
|
if self.debug and substituted_expr != expr:
|
||||||
|
print(f"🔄 Sustitución parcial: {var_name} = {expr} → {substituted_expr}")
|
||||||
|
else:
|
||||||
|
# No hay sustituciones disponibles, mantener expresión original
|
||||||
|
substituted[var_name] = expr
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
if self.debug:
|
||||||
|
print(f"⚠️ Error en sustitución automática para {var_name}: {e}")
|
||||||
|
# En caso de error, mantener expresión original
|
||||||
|
substituted[var_name] = expr
|
||||||
|
|
||||||
|
return substituted
|
||||||
|
|
||||||
def _assign_variable(self, var_name: str, expression) -> str:
|
def _assign_variable(self, var_name: str, expression) -> str:
|
||||||
"""Asigna un valor a una variable"""
|
"""Asigna un valor a una variable"""
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -1,82 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
"""
|
|
||||||
Prueba de las correcciones:
|
|
||||||
1. FourBytes + int mantiene tipo FourBytes
|
|
||||||
2. IP4Mask con mejor mensaje de error para máscaras inválidas
|
|
||||||
"""
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
print("🔧 PROBANDO CORRECCIONES")
|
|
||||||
print("=" * 50)
|
|
||||||
|
|
||||||
try:
|
|
||||||
from main_evaluation import HybridEvaluationEngine
|
|
||||||
|
|
||||||
# Crear motor
|
|
||||||
engine = HybridEvaluationEngine()
|
|
||||||
|
|
||||||
print("📋 Reproduciendo casos del usuario:\n")
|
|
||||||
|
|
||||||
# 1. Reproducir secuencia completa
|
|
||||||
print("1. mask=255.240.0.3")
|
|
||||||
result1 = engine.evaluate_line("mask=255.240.0.3")
|
|
||||||
print(f" → {result1.result} (tipo: {type(result1.result).__name__})")
|
|
||||||
|
|
||||||
print(f"\n2. mask")
|
|
||||||
result2 = engine.evaluate_line("mask")
|
|
||||||
print(f" → {result2.result} (tipo: {type(result2.result).__name__})")
|
|
||||||
|
|
||||||
print(f"\n3. ip=10.1.1.x")
|
|
||||||
result3 = engine.evaluate_line("ip=10.1.1.x")
|
|
||||||
print(f" → {result3.result} (tipo: {type(result3.result).__name__})")
|
|
||||||
|
|
||||||
print(f"\n4. 10.1.1.1 + 1 (DEBE DEVOLVER FourBytes)")
|
|
||||||
result4 = engine.evaluate_line("10.1.1.1 + 1")
|
|
||||||
print(f" → {result4.result} (tipo: {type(result4.result).__name__})")
|
|
||||||
|
|
||||||
if hasattr(result4.result, 'original'):
|
|
||||||
print(f" → Valor original: {result4.result.original}")
|
|
||||||
|
|
||||||
print(f"\n5. ip")
|
|
||||||
result5 = engine.evaluate_line("ip")
|
|
||||||
print(f" → {result5.result} (tipo: {type(result5.result).__name__})")
|
|
||||||
|
|
||||||
print(f"\n6. IP4(10.1.1.4)")
|
|
||||||
result6 = engine.evaluate_line("IP4(10.1.1.4)")
|
|
||||||
print(f" → {result6.result} (tipo: {type(result6.result).__name__})")
|
|
||||||
|
|
||||||
print(f"\n7. IP4Mask(mask) - DEBE DAR ERROR INFORMATIVO")
|
|
||||||
result7 = engine.evaluate_line("IP4Mask(mask)")
|
|
||||||
if result7.is_error:
|
|
||||||
print(f" ❌ Error (como esperado): {result7.error}")
|
|
||||||
else:
|
|
||||||
print(f" → {result7.result} (tipo: {type(result7.result).__name__})")
|
|
||||||
|
|
||||||
print(f"\n8. Probando con máscara válida: IP4Mask(255.255.0.0)")
|
|
||||||
result8 = engine.evaluate_line("IP4Mask(255.255.0.0)")
|
|
||||||
print(f" → {result8.result} (tipo: {type(result8.result).__name__})")
|
|
||||||
|
|
||||||
print(f"\n🎯 RESUMEN DE RESULTADOS:")
|
|
||||||
print(f" ✅ mask asignada como FourBytes: {type(result1.result).__name__ == 'FourBytes'}")
|
|
||||||
print(f" ✅ 10.1.1.1 + 1 mantiene FourBytes: {type(result4.result).__name__ == 'FourBytes'}")
|
|
||||||
print(f" ✅ IP4Mask da error informativo para máscara inválida: {result7.is_error}")
|
|
||||||
print(f" ✅ IP4Mask funciona con máscara válida: {not result8.is_error}")
|
|
||||||
|
|
||||||
# Verificación adicional de aritmética FourBytes
|
|
||||||
print(f"\n🔍 VERIFICACIÓN ADICIONAL DE ARITMÉTICA:")
|
|
||||||
|
|
||||||
# Test más casos aritméticos
|
|
||||||
test_cases = [
|
|
||||||
"192.168.1.1 + 5",
|
|
||||||
"10.0.0.0 + 256",
|
|
||||||
"255.255.255.255 - 1"
|
|
||||||
]
|
|
||||||
|
|
||||||
for case in test_cases:
|
|
||||||
result = engine.evaluate_line(case)
|
|
||||||
print(f" {case} → {result.result} ({type(result.result).__name__})")
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error: {e}")
|
|
||||||
import traceback
|
|
||||||
traceback.print_exc()
|
|
|
@ -1,75 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
"""
|
|
||||||
Prueba específica de FourBytes + int
|
|
||||||
"""
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
print("🔍 PROBANDO FourBytes + int")
|
|
||||||
print("=" * 40)
|
|
||||||
|
|
||||||
try:
|
|
||||||
from main_evaluation import HybridEvaluationEngine
|
|
||||||
|
|
||||||
# Crear motor
|
|
||||||
engine = HybridEvaluationEngine()
|
|
||||||
|
|
||||||
# 1. Crear FourBytes directamente
|
|
||||||
print("1. Creando FourBytes directamente:")
|
|
||||||
FourBytes = engine.base_context.get('FourBytes')
|
|
||||||
print(f" FourBytes: {FourBytes}")
|
|
||||||
|
|
||||||
fb = FourBytes("10.1.1.1")
|
|
||||||
print(f" fb = {fb} (tipo: {type(fb)})")
|
|
||||||
print(f" fb._numeric_value = {fb._numeric_value}")
|
|
||||||
|
|
||||||
# 2. Probar suma directa
|
|
||||||
print(f"\n2. Suma directa en Python:")
|
|
||||||
result_direct = fb + 1
|
|
||||||
print(f" fb + 1 = {result_direct} (tipo: {type(result_direct)})")
|
|
||||||
|
|
||||||
# 3. Probar a través del motor de evaluación
|
|
||||||
print(f"\n3. Evaluación a través del motor:")
|
|
||||||
engine.symbol_table['test_fb'] = fb
|
|
||||||
|
|
||||||
result_engine = engine.evaluate_line("test_fb + 1")
|
|
||||||
print(f" test_fb + 1 = {result_engine.result} (tipo: {type(result_engine.result)})")
|
|
||||||
|
|
||||||
# 4. Probar tokenización + evaluación
|
|
||||||
print(f"\n4. Tokenización completa:")
|
|
||||||
result_tokenized = engine.evaluate_line("10.1.1.1 + 1")
|
|
||||||
print(f" 10.1.1.1 + 1 = {result_tokenized.result} (tipo: {type(result_tokenized.result)})")
|
|
||||||
|
|
||||||
# 5. Verificar paso a paso qué pasa en la tokenización
|
|
||||||
print(f"\n5. Análisis paso a paso:")
|
|
||||||
from tl_bracket_parser import UniversalTokenizer
|
|
||||||
tokenizer = UniversalTokenizer()
|
|
||||||
tokenizer.debug = True
|
|
||||||
|
|
||||||
tokenized = tokenizer.preprocess_tokens("10.1.1.1 + 1")
|
|
||||||
print(f" Tokenizado: {tokenized}")
|
|
||||||
|
|
||||||
# 6. Evaluar el tokenizado directamente
|
|
||||||
print(f"\n6. Evaluando tokenizado directamente:")
|
|
||||||
try:
|
|
||||||
direct_eval = engine._eval_in_context(tokenized)
|
|
||||||
print(f" Resultado directo: {direct_eval} (tipo: {type(direct_eval)})")
|
|
||||||
except Exception as e:
|
|
||||||
print(f" Error: {e}")
|
|
||||||
|
|
||||||
# 7. Probar operación manual paso a paso
|
|
||||||
print(f"\n7. Operación manual paso a paso:")
|
|
||||||
try:
|
|
||||||
fb_manual = engine._eval_in_context('FourBytes("10.1.1.1")')
|
|
||||||
print(f" FourBytes manual: {fb_manual} (tipo: {type(fb_manual)})")
|
|
||||||
|
|
||||||
add_result = engine._eval_in_context('FourBytes("10.1.1.1") + 1')
|
|
||||||
print(f" Suma manual: {add_result} (tipo: {type(add_result)})")
|
|
||||||
except Exception as e:
|
|
||||||
print(f" Error en operación manual: {e}")
|
|
||||||
import traceback
|
|
||||||
traceback.print_exc()
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error: {e}")
|
|
||||||
import traceback
|
|
||||||
traceback.print_exc()
|
|
Loading…
Reference in New Issue