Hasta ahora nos hemos
referido a las nuevas posibilidades que Visual LISP aporta para el desarrollo
de aplicaciones. Pero en el desarrollo de programas nos toparemos
inevitablemente con errores que deberán ser detectados y corregidos. Para ello
las herramientas que examinaremos a continuación.
Evaluación inmediata del código
La primera opción de que disponemos es la evaluación
inmediata de cada línea de código escrita. A medida que vamos escribiendo en la
ventana del editor, es posible seleccionar el código que deseemos comprobar y
pulsar el botón Cargar Selección (ver figura 1).
Figura 1. Barra de Herramientas Ejecutar: carga, comprueba,
formatea y comenta el código.
Figura 2. Ventana del Editor con código seleccionado y
punto de interrupción.
De inmediato se evalúa el código seleccionado, En la figura
2 mostramos el código de un programa que permite extraer de la lista de entidad
de una LWPOYLINE las coordenadas de sus vértices. Seleccionando la línea
(setq lista (entget (car (entsel))))
y cargando esta selección, pasamos a la pantalla de AutoCAD
donde se nos pide designar un objeto gráfico. A continuación, la consola Visual
LISP nos mostrará el resultado devuelto, que habrá quedado almacenado en la
variable lista.
Para comprobar la naturaleza de este dato basta situar el
cursor sobre el nombre de esta variable y pulsar el botón Inspeccionar (ver
figura 3).
Figura 3. Barra de Herramientas Ver: inspector de
variables, rastreo de la ejecución, servicio de símbolos, búsqueda por
aproximación y ventana de inspección en tiempo real.
Así, línea a línea sería posible ir comprobando los efectos
de las diversas funciones que podemos usar para lograr determinado objetivo.
¿Qué sucedería si nuestro código encerrara un error? Supongamos que hemos
olvidado introducir en esta línea de código la función car. En este caso, en lugar de un nombre de entidad
obtendremos una lista del tipo:
(<Nombre de
entidad: 16ca638> (0.591659 0.594869 0.0))
que al ser pasada a la función entget
provocaría un error reflejado en la Consola con el
mensaje:
; error: tipo de
argumento erróneo: lentityp (<Nombre de entidad: 16d0638> (0.591659
0.594869 0.0))
donde lentityp
es
un predicado que indica la naturaleza del argumento que la función entget
esperaba recibir (un nombre de
entidad) y lo que realmente ha recibido. La Tabla 1 muestra algunos predicados
asociados a mensajes de error.
La documentación de Visual LISP es deficiente en este
sentido, no aclarando el significado de estos mensajes.
Predicado:
|
Argumento que se espera:
|
stringp
|
De tipo cadena (string)
|
numberp
|
Numérico (real o entero)
|
listp
|
Una lista
|
fixnump
|
Un número entero
|
lentityp
|
Un nombre de entidad
|
lselsetp
|
Un conjunto de selección
|
VLA-OBJECT
|
Un objeto Visual LISP ActiveX
|
output-streamp
|
Una salida a archivo de texto
|
streamp
|
Un archivo abierto para
lectura o escritura
|
Tabla 1. Predicados asociados a mensajes de error
Puntos de interrupción (Break Points)
Identificada una función problemática, desearemos ver su
funcionamiento paso a paso. Introduciendo puntos de interrupción se detendrá la
ejecución del programa permitiendo comprobar su operación en detalle. Para ello
disponemos del botón Activar/Desactivar Punto de Interrupción (ver
figura 4), la correspondiente opción del menú Depurar (Debug) o
simplemente la tecla de función F9.
Figura 4. Barra de Herramientas Depurar: control de la
evaluación en modo interrupción, colocación de puntos de interrupción y añadir
variables a inspeccionar.
El programa se ejecutará hasta llegar al primer punto de
interrupción. Al llegar ahí, el control pasa a la Consola y vemos resaltada la
expresión en la ventana del Editor. Observemos que el símbolo (prompt)
de la consola aparece ahora numerado: _1_$
lo que nos indica que estamos en un nuevo bucle de evaluación (read-eval-print
loop) anidado bajo el bucle superior (top-level) que es donde se ha
llamado al programa. Podemos controlar el paso a que se evalúan las expresiones
mediante los botones Entrar (Step Into) que se detiene en cada
expresión anidada, Pasar al Siguiente (Step Over) que evalúa toda
la expresión resaltada, o Ir al Final (Step Out) que busca el
final de la función donde el programa se ha detenido y efectúa la evaluación
hasta allí.
Durante este estado de interrupción podemos evaluar
expresiones en la Consola que nos den información sobre el contenido de las
variables (tecleando el nombre de la variable y pulsando INTRO) e incluso
cambiar el contenido de las mismas a partir de la evaluación de cualquier
función en la consola o empleando el Servicio de Símbolos (ver Figura
5).
Figura 5. Ventana del Servicio de Símbolos
Pulsando el botón Continuar (ver figura 4), se pasará
al próximo punto de interrupción si lo hubiera. Para ascender un nivel (ya que
pueden darse varios bucles de interrupción anidados) se pulsará el botón Descartar
(Quit Current Level) y para regresar directamente al nivel superior el
botón Restablecer (Reset to Top Level).
El programa entrará de manera automática en un bucle de
interrupción al encontrar un error en tiempo de ejecución, siempre que se
encuentre activada la opción Interrupción en Error (Break on Error)
del menú Depurar (Debug). En ese estado tendremos acceso al
contenido de todas las variables del entorno en que se ha producido el error,
pero no será posible continuar la ejecución.
Para conservar los puntos de interrupción de una sesión de
trabajo a otra será necesario Guardar Parámetros (Save Settings)
desde el menú Herramientas (Tools). Los puntos de interrupción se
pierden al aplicar las operaciones de formateo automático.
La ventana Inspección (Watch)
Tenemos también la posibilidad de vigilar los valores que
devuelven las funciones. Para ello es la ventana Inspección (Watch).
Para abrirla con el valor de la última expresión evaluada se puede seleccionar
la opción Inspeccionar Ultima Evaluación (Watch Last Evaluation)
del menú Depurar. O bien pulsar el botón de la barra de herramientas
correspondiente (ver figura 4), que abre el diálogo Añadir Inspección (Add
Watch). Si el cursor estuviera situado sobre el nombre de alguna variable,
este aparecería en la casilla de lista desplegable. En caso contrario, podemos
escribir su nombre o elegir el valor por defecto que es la variable global *LAST-VALUE*
(última evaluación). La ventana
Inspección (ver figura 6) se actualiza a medida que los valores de los
símbolos inspeccionados cambian. Así, al entrar en un bucle de interrupción
tendremos siempre a la vista los valores actuales. En cualquier momento estos
valores pueden ser copiados a la ventana de Rastreo (Trace)
mediante el botón Copiar en Rastreo/Registro (Copy to Trace/Log).
Si estuviera activada la opción Act/Des Registro de Rastreo, accesible
desde el menú contextual de la ventana de Rastreo, esta información
también se copiaría a un archivo de extensión LOG.

Figura 6. Inspección de las variables seleccionadas en
tiempo real.
La opción de Animar
El menú Depurar nos ofrece la opción de Animar
(Animate). Al activar esta opción, la ejecución del programa se hará
toda en modo de interrupción como si pulsáramos continuamente el botón Entrar
(Step Into). El intervalo de tiempo entre la evaluación de cada
expresión es configurable desde Herramientas>Opciones de
Entorno>Opciones Generales (ficha Diagnóstico). Para detener la
animación puede pulsarse la tecla PAUSA (BREAK) y de esa manera observar y
cambiar si fuera necesario el valor de las variables o colocar nuevos puntos de
interrupción. Al encontrar un punto de interrupción en modo Animar,
deberemos usar los botones Entrar, Pasar a Siguiente o Ir al
Final para continuar la evaluación. Tanto en uno como en otro caso, la
ejecución en modo Animar se reinicia pulsando el botón Continuar.
El modo Animar es sumamente instructivo especialmente cuando en el
programa incluye bucles anidados.
La Pila de Rastreo (Trace Stack)
La Pila de Rastreo contiene el registro histórico de
la ejecución de funciones dentro del programa. Una Pila (Stack)
es una estructura de programación que se caracteriza por el orden de entrada y
salida de los elementos que almacena: el último elemento en entrar es el
primero en salir. Su inspección (durante una interrupción del programa) permite
observar lo que sucede durante la ejecución.
El invocar una función hace que se incluya un elemento en la
pila. Cuando se llama a otras funciones anidadas, pueden añadirse a ella nuevos
elementos. Esto se hará siempre que sea necesario a Visual LISP para recordar
la vía de salida. En una pila pueden aparecer cinco tipos de elementos (ver
Tabla 2).
Elemento
|
Contenido
|
Llamadas a funciones
|
nivel (nombre-función {argumento 1} ... )
se presentan los argumentos realmente pasados a la función
|
Palabras clave
|
nivel :palabra_clave- (datos opcionales)
ocupan los niveles superior e inferior de la pila
|
Formas del nivel
superior
|
acciones iniciadas al teclear una expresión en la Consola
o al cargar un archivo o una selección.
|
Formas lambda
|
se incluye cada vez que se encuentra una expresión lambda en el programa
|
Formas especiales
|
nivel (forma-función ...)
muestran las llamadas a
funciones foreach y repeat . Los argumentos no se
muestran
|
Tabla 2. Elementos de la Pila de Rastreo
Para obtener más información acerca de cualquiera de los
elementos de la pila se deberá seleccionar y llamar al menú contextual pulsando
el botón derecho del ratón (ver figura 7). Algunas opciones de especial interés
son:
- Variables Locales (Local Variables): examina el
valor que poseían las variables locales en el momento de ejecutarse la función
- Posición de Origen (Source Position): muestra el código
fuente resaltándolo en la ventana del editor.
- Origen del Punto de Llamada (Call Point Source):
curiosamente traducido por Autodesk como "Ejecutar Origen de
Punto", muestra la posición de la expresión de llamada, al igual que
la opción anterior. La diferencia radica en que, según el elemento
seleccionado, estará disponible una u otra opción, y a veces ambas.
Figura 7. Pila de Rastreo con su menú contextual.
Palabras Clave
Una palabra clave indica una operación específica que tiene
lugar en el entorno VLISP. La Tabla 3 muestra algunas de las palabras clave que
sólo aparecerán en el fondo de la pila.
Palabra clave
|
Operación
|
:ACAD-REQUEST
|
La llamada a la función que le sigue en la pila (más
arriba) fue invocada desde la línea de comandos de AutoCAD.
|
:DCL-ACTION
|
Acción llamada desde un cuadro de diálogo. A la palabra
clave le siguen dos cadenas: el nombre del diálogo y el valor de la variable $KEY. Si un número, representa el
valor de la variable $REASON.
El elemento que le sigue en la casilla de arriba describe la llamada a
función construida a partir de la cadena asociada al botón de acción.
|
:TOP-COMMAND
|
Función invocada al cargar un archivo o selección.
|
:USER-INPUT
|
Tecleado en la Consola. La
casilla de arriba muestra la expresión resultante.
|
Tabla 3. Palabras clave (fondo de la Pila)
Entre las palabras clave más frecuentes que pueden aparecer
en la parte superior de la pila están las que muestra la Tabla 4.
Palabra clave
|
Operación
|
:BEFORE-EXP
|
Indica que un programa se está depurando en modo
interrupción. Indica que se ha entrado en una expresión.
|
:AFTER-EXP
|
Igual que el anterior, al salir de una expresión.
|
:ARQ-SUBR-CALLBACK
|
Llamada normal de AutoCAD a una función definida en VLISP.
|
:BREAK-POINT
|
Punto de interrupción especificado por el usuario.
|
:ERROR-BREAK
|
Error en tiempo de ejecución. La opción Mostrar Mensaje
(Show Message) del menú contextual muestra mensajes de error más
específicos.
|
:FUNCTION-ENTRY
|
Interrupción al entrar en una función, el elemento
siguiente muestra la llamada a dicha función
|
:KBD-BREAK
|
Se ha pulsado la tecla PAUSA.
|
:READ-ERROR
|
Error durante una operación de lectura.
|
:SYNTAX-ERROR
|
Se ha detectado una
sintaxis AutoLISP incorrecta
|
Tabla 4. Palabras clave (extremo superior de la Pila)
Rastreo de Errores
Cuando se produce un error, el estado de la Pila de Rastreo
se copia automáticamente a la ventana de Rastreo de Errores (Error
Trace), a la que se accede desde el menú Ver>Rastreo de Errores (View>Error
Trace).
Como copia que es de la Pila de Rastreo, todo lo
explicado sobre ésta se aplica al Rastreo de Errores. La única
diferencia es la siguiente:
Tanto en la ventana de la Pila de Rastreo como la de Rastreo
de Errores hay dos botones. El de la izquierda sirve para Renovar (Refresh)
el contenido de la ventana. Cuando se pulsa este botón después de salir de un
bucle de interrupción pasando al bucle de nivel superior, el Renovar la Pila
de Rastreo cambiará su contenido para reflejar la situación actual,
mientras que Renovar el Rastreo de Errores no cambiará su
contenido a menos que se haya producido un nuevo error (ver figura 8).
Figura 8. Comparación entre la Pila de Rastreo y el Rastreo
de Errores. Se ha introducido la función strcat,
ilegal en este contexto, para provocar intencionalmente el error.
Conclusiones
Hemos visto las principales herramientas de que dispone el
IDE Visual LISP para la depuración de errores. No debemos olvidar las otras
ayudas disponibles desde el mismo Editor, tales como la sintaxis coloreada
(basta ver un nombre de función que no se coloree de azul para saber que está
mal escrito), la detección del cierre de los paréntesis, la revisión de
sintaxis, el formateo automático o la introducción de comentarios al cierre de
las expresiones (ver figura 1). Sin olvidar la comprobación ulterior que se
realiza al momento de compilar la función que ya comentamos en nuestro artículo
del mes pasado. Con todo ello disponemos de un entorno poderoso para el
desarrollo de las aplicaciones más complejas.