4.5. Depurar el código Visual LISP

Hasta ahora nos hemosreferido a las nuevas posibilidades que Visual LISP aporta para el desarrollode aplicaciones. Pero en el desarrollo de programas nos toparemosinevitablemente con errores que deberán ser detectados y corregidos. Para ellolas herramientas que examinaremos a continuación.


Evaluación inmediata del código

La primera opción de que disponemos es la evaluacióninmediata de cada línea de código escrita. A medida que vamos escribiendo en laventana del editor, es posible seleccionar el código que deseemos comprobar ypulsar 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 ypunto de interrupción.

De inmediato se evalúa el código seleccionado, En la figura2 mostramos el código de un programa que permite extraer de la lista de entidadde 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 AutoCADdonde se nos pide designar un objeto gráfico. A continuación, la consola VisualLISP nos mostrará el resultado devuelto, que habrá quedado almacenado en lavariable lista.

Para comprobar la naturaleza de este dato basta situar elcursor sobre el nombre de esta variable y pulsar el botón Inspeccionar (verfigura 3).


Figura 3. Barra de Herramientas Ver: inspector devariables, rastreo de la ejecución, servicio de símbolos, búsqueda poraproximación y ventana de inspección en tiempo real.

Así, línea a línea sería posible ir comprobando los efectosde las diversas funciones que podemos usar para lograr determinado objetivo.¿Qué sucedería si nuestro código encerrara un error? Supongamos que hemosolvidado introducir en esta línea de código la función car. En este caso, en lugar de un nombre de entidadobtendremos una lista del tipo:

(<Nombre deentidad: 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 elmensaje:

; error: tipo deargumento erróneo: lentityp (<Nombre de entidad: 16d0638> (0.5916590.594869 0.0))

donde lentityp esun predicado que indica la naturaleza del argumento que la función entget esperaba recibir (un nombre deentidad) y lo que realmente ha recibido. La Tabla 1 muestra algunos predicadosasociados a mensajes de error.

La documentación de Visual LISP es deficiente en estesentido, 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 sufuncionamiento paso a paso. Introduciendo puntos de interrupción se detendrá laejecución del programa permitiendo comprobar su operación en detalle. Para ellodisponemos del botón Activar/Desactivar Punto de Interrupción (verfigura 4), la correspondiente opción del menú Depurar (Debug) osimplemente la tecla de función F9.

Figura 4. Barra de Herramientas Depurar: control de laevaluación en modo interrupción, colocación de puntos de interrupción y añadirvariables a inspeccionar.

El programa se ejecutará hasta llegar al primer punto deinterrupción. Al llegar ahí, el control pasa a la Consola y vemos resaltada laexpresió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-printloop) anidado bajo el bucle superior (top-level) que es donde se hallamado al programa. Podemos controlar el paso a que se evalúan las expresionesmediante los botones Entrar (Step Into) que se detiene en cadaexpresión anidada, Pasar al Siguiente (Step Over) que evalúa todala expresión resaltada, o Ir al Final (Step Out) que busca elfinal de la función donde el programa se ha detenido y efectúa la evaluaciónhasta allí.

Durante este estado de interrupción podemos evaluarexpresiones en la Consola que nos den información sobre el contenido de lasvariables (tecleando el nombre de la variable y pulsando INTRO) e inclusocambiar el contenido de las mismas a partir de la evaluación de cualquierfunción en la consola o empleando el Servicio de Símbolos (ver Figura5).

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 quepueden darse varios bucles de interrupción anidados) se pulsará el botón Descartar(Quit Current Level) y para regresar directamente al nivel superior elbotón Restablecer (Reset to Top Level).

El programa entrará de manera automática en un bucle deinterrupción al encontrar un error en tiempo de ejecución, siempre que seencuentre activada la opción Interrupción en Error (Break on Error)del menú Depurar (Debug). En ese estado tendremos acceso alcontenido 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 detrabajo a otra será necesario Guardar Parámetros (Save Settings)desde el menú Herramientas (Tools). Los puntos de interrupción sepierden al aplicar las operaciones de formateo automático.

La ventana Inspección (Watch)

Tenemos también la posibilidad de vigilar los valores quedevuelven las funciones. Para ello es la ventana Inspección (Watch).Para abrirla con el valor de la última expresión evaluada se puede seleccionarla opción Inspeccionar Ultima Evaluación (Watch Last Evaluation)del menú Depurar. O bien pulsar el botón de la barra de herramientascorrespondiente (ver figura 4), que abre el diálogo Añadir Inspección (AddWatch). Si el cursor estuviera situado sobre el nombre de alguna variable,este aparecería en la casilla de lista desplegable. En caso contrario, podemosescribir su nombre o elegir el valor por defecto que es la variable global *LAST-VALUE* (última evaluación). La ventanaInspección (ver figura 6) se actualiza a medida que los valores de lossímbolos inspeccionados cambian. Así, al entrar en un bucle de interrupcióntendremos siempre a la vista los valores actuales. En cualquier momento estosvalores 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, accesibledesde el menú contextual de la ventana de Rastreo, esta informacióntambién se copiaría a un archivo de extensión LOG.

Figura 6. Inspección de las variables seleccionadas entiempo 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 cadaexpresión es configurable desde Herramientas>Opciones deEntorno>Opciones Generales (ficha Diagnóstico). Para detener laanimación puede pulsarse la tecla PAUSA (BREAK) y de esa manera observar ycambiar si fuera necesario el valor de las variables o colocar nuevos puntos deinterrupción. Al encontrar un punto de interrupción en modo Animar,deberemos usar los botones Entrar, Pasar a Siguiente o Ir alFinal para continuar la evaluación. Tanto en uno como en otro caso, laejecución en modo Animar se reinicia pulsando el botón Continuar.El modo Animar es sumamente instructivo especialmente cuando en elprograma incluye bucles anidados.

La Pila de Rastreo (Trace Stack)

La Pila de Rastreo contiene el registro histórico dela ejecución de funciones dentro del programa. Una Pila (Stack)es una estructura de programación que se caracteriza por el orden de entrada ysalida de los elementos que almacena: el último elemento en entrar es elprimero en salir. Su inspección (durante una interrupción del programa) permiteobservar lo que sucede durante la ejecución.

El invocar una función hace que se incluya un elemento en lapila. Cuando se llama a otras funciones anidadas, pueden añadirse a ella nuevoselementos. Esto se hará siempre que sea necesario a Visual LISP para recordarla vía de salida. En una pila pueden aparecer cinco tipos de elementos (verTabla 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 loselementos de la pila se deberá seleccionar y llamar al menú contextual pulsandoel botón derecho del ratón (ver figura 7). Algunas opciones de especial interésson:

  • Variables Locales (Local Variables): examina elvalor que poseían las variables locales en el momento de ejecutarse la función
  • Posición de Origen (Source Position): muestra el códigofuente resaltándolo en la ventana del editor.
  • Origen del Punto de Llamada (Call Point Source):curiosamente traducido por Autodesk como "Ejecutar Origen dePunto", muestra la posición de la expresión de llamada, al igual quela opción anterior. La diferencia radica en que, según el elementoseleccionado, 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 tienelugar en el entorno VLISP. La Tabla 3 muestra algunas de las palabras clave quesó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 apareceren 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 Rastreose copia automáticamente a la ventana de Rastreo de Errores (ErrorTrace), a la que se accede desde el menú Ver>Rastreo de Errores (View>ErrorTrace).

Como copia que es de la Pila de Rastreo, todo loexplicado sobre ésta se aplica al Rastreo de Errores. La únicadiferencia es la siguiente:

Tanto en la ventana de la Pila de Rastreo como la de Rastreode 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 unbucle de interrupción pasando al bucle de nivel superior, el Renovar la Pilade Rastreo cambiará su contenido para reflejar la situación actual,mientras que Renovar el Rastreo de Errores no cambiará sucontenido a menos que se haya producido un nuevo error (ver figura 8).

Figura 8. Comparación entre la Pila de Rastreo y el Rastreode 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 elIDE Visual LISP para la depuración de errores. No debemos olvidar las otrasayudas 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 desintaxis, el formateo automático o la introducción de comentarios al cierre delas expresiones (ver figura 1). Sin olvidar la comprobación ulterior que serealiza al momento de compilar la función que ya comentamos en nuestro artículodel mes pasado. Con todo ello disponemos de un entorno poderoso para eldesarrollo de las aplicaciones más complejas.