PostScript II: La pila de operandos, manipulaciones y operadores matem'aticos

ArticleCategory:[Artikel Kategorie]

Software Development

AuthorImage:[Bild des Autors]

[Photo of the Author]

TranslationInfo:[Translation history]

original in en Emre Demiralp

en to es David Abilleira Freijeiro

en to en Jorge M. Paulo y Jose Quesada

AboutTheAuthor:[Über den Autor]

Soy un estudiante en el Istanbul American Robert College, y a la vez, uno de los administradores del Computer Labs en la Faculty of Arts and Sciences en la Istanbul Technical University. El sistema operativo que domina sobre todos los demás en estos laboratorios es LINUX. Intereses: PovRay y PostScript, animación, diseño de CDs, programación, holografía, etc.. usuario de Linux desde 1994.

Abstract:[Zusammenfassung]

Gota a gota, se hace un lago
-Proverbio Turco-.

El autor describe la pila de operandos del lenguaje PostScript. Se presentan aquí las manipulaciones de la pila y los operadores matemáticos. Este artículo no cubre todas las propiedades de la pila de operandos. Los artículos siguientes continuarán hablando acerca de ello.

ArticleIllustration:[Titelbild des Artikels]

[Ilustration]

ArticleBody:[Der eigentliche Artikel

Introducci'on

Este es el segundo de una serie de artículos acerca de PostScript. El propósito principal de este artículo es comentar el manejo de la pila. La pila de operandos es quizás la parte más importante de PostScript. Asignaciones, operaciones aritméticas o matemáticas, bucles y operaciones lógicas son manejadas en esta porción de memoria específica. ¡Sí! La pila es una región especial de memoria que PostScript usa para ejecutar casi cualquier cosa que nosotros queramos que PostScript haga. La pila mantiene la información en orden de forma que el último dato introducido sale primero. Puedes visualizar esto como una tubería con uno de sus extremos cerrado. Cuando pones algo en esta tubería, empujará todos los elementos que ya estaban en ella hacia el extremo cerrado para hacer sitio para el mismo. Por lo tanto el último elemento en entrar será siempre el más cercano al extremo abierto de la tubería. Los elementos en la pila pueden ser cadenas de texto, constantes numéricas, claves, bloques, ...  

Manipulación de la pila

A pesar de que los elementos se ordenan en la pila, hay algunas operaciones de pila que nos permiten reordenar los elementos. Las "manipulaciones" se aplican a uno o más de los elementos de la pila. Los operadores, por definición, manipulan elemento(s) en la pila. Los operadores pueden o no necesitar parámetros (operandos en la terminología PostScript) dependiendo del caracter de la manipulación.  Si necesitan el(los) parámetro(s) entonces estos deben ser apilados en la pila primero. El operador toma acción entonces con respecto a estos operandos..  Aquí se da una lista de estos operadores con las explicaciones necesarias. Además se dan algunos ejemplos para ilustrarlo con más detalle. 

pop:
Este operador descarta el elemento que está en la cima de la pila de operandos (el último en ser introducido).
exch:
Este operador intercambia los dos elementos que se encuentran en las posiciones más elevadas de la pila de operandos. 
dup:
Este operador crea una copia del último elemento introducido en la pila de operandos y lo apila en ella. En otras palabras, duplica el elemento de más arriba de la pila. 
copy:
Este operador necesita un operando entero (parámetro) que se debe introducir en la pila de operandos antes de que el operador actúe. Si le llamamos n a este parámetro entero, entonces el comando será n copy. Cuando se ejecuta el comando, se realiza una copia de los n elementos de la cima (los últimos en ser introducidos) y se colocan en la pila de operandos como los últimos elementos introducidos. En otras palabras, copy es un operador de duplicación de conjuntos. 
index:
Este operador necesita un operando entero que se debe introducir en la pila de operandos antes de que el operador actúe. Si llamamos n a ese parámetro entero entonces el comando se introducirá como n index. Cuando esto se ejecuta, se crea una copia de los n elementos de las posiciones superiores de la pila (los últimos en ser introducidos) y se situa en la pila de operandos como el último elemento en ser introducidos. En otras palabras, index puede seleccionar un elemento interno y crear y situar una copia en la pila de operandos. El indexado de elementos empieza a partir del elemento de más arriba (él último) con el número 0
roll:
Este operador necesita dos parámetros enteros que se deben introducir en la pila de operandos antes de que el operador actúe. Si llamamos m y n a esos dos parámetros enteros entonces el comando será introducido como m n roll. Aquí m denota cuantos elementos serán rotados mientras n indica el número de rotaciones. Una rotación se define de manera que el elemento de más arriba de la pila de operandos llega a ser el elemento m-esimo mientras el conjunto de m-1 elementos bajo el elemento de la cima son desplazados un lugar hacia la cima. Este esquema es válido cuando n es igual a 1. Si fuese 2 entonces ocurrirían dos rotaciones consecutivas. En otras palabras m 2 roll es lo mismo que m 1 roll m 1 roll. El parámetro n puede tomar valores negativos. Si esto ocurre, se invierte la acción que ocurre cuando n es positivo. Esto significa que el efecto global del comando m n roll m -n roll es neutro. Esto deja la pila de operando sin cambio alguno. El indexado de los elementos empieza por el elemento de la cima que se considera que ocupa la posición 0
clear:
Este operador descarta todos los elementos de la pila de operandos. 
count:
Este operador cuenta los elementos de la pila de operandos. El resultado se apila en la pila de operandos como un elemento nuevo. Si no quieres este nuevo elemento entonces puedes formar el comando compuesto count pstack pop donde pop elimina el nuevo elemento que count ha creado después de que el resultado del conteo sea visualizado a través de la actuación del operando de fichero pstack.  
mark:
Este operador coloca un elemento -marktype- en la pila de operandos. Este elemento se puede usar para dividir el conjunto de elementos de la pila de operandos en subconjuntos. Hay otras dos operaciones cleartomark y counttomark que buscan este elemento para sus acciones. Si no lo encuentran emiten un mensaje de error. 
cleartomark:
Este operador elimina todos los elementos desde el que está en la cima hasta el primer -marktype-. Este objeto -marktype- se elimina también. Si no hay ningún objeto marktype en la pila de operandos, se emite un mensaje de error. 
counttomark:
Este operador cuenta todos lo elementos empezando desde el elemento de la cima hasta encontrar el objeto -marktype-. El resultado que es un valor entero se apila en la pila de operandos como el último elemento. El primer elemento -marktype- no se incluye en el resultado. Si no hay ningún elemento marktype en la pila de operandos PostScript informa el error y no hace nada. 

Permitenos decir algo ahora acerca de la pila. Si quieres ver en acción a los operadores anteriores, debes activar primero el interprete Postscript. Como se mencionó en el primer artículo, en el mundo Linux se usa un interprete disponible publicamente, de nombre ghostscript. Ghostscript puede activarse de diferentes maneras mediante el paso de los parámetros apropiados en la linea de comandos. La forma habitual de hacerlo es teclear gs en el entorno X Window. A veces puede que no funcione debido a algún problema de configuración en X. Se visualizará un mensaje de error acerca de la incapacidad de crear un consola gráfica. Entonces o bien solucionas esos problemas o puedes forzar a ghostscript a usar el dispositivo x11. Para conseguirlo debes teclear gs -sDEVICE=x11. Tanto esto como un simple gs (si esto último funciona) crea un ventana vacía con el fondo blanco que se usará para los mensajes que se crearán durante la sesión. Dado que los mensajes (displays) no se tratan en este artículo no necesitamos esta ventana y es posible librarse de ella. Para ello, se puede activar el interprete ghostscript sin displays tecleando el parámetro -dNODISPLAY en la linea de comandos después de gs o de gs -sDEVICE=x11. Si se hace esto, se visualizará una cabecera de copyright seguida del prompt de ghostscript GS> al principio de una nueva linea. En este punto, ghostscript está preparado para tus comandos. La pila de operandos está vacía.

Para ver el contenido de la pila de operandos puedes usar el operador de fichero pstack. Se le llama operador de fichero porque envía información acerca del contenido de la pila al fichero de salida estandar que por defecto es la pantalla. Si introduces este comando en el prompt no se visualiza nada y un nuevo prompt GS> aparecerá al principio de una nueva linea. Esto significa que la pila de operandos está vacía. 

Para introducir elementos en la pila de operandos puedes teclear los elementos en el prompt. Por ejemplo si quieres introducir 1 como un elemento, solo tienes que teclear 1 en el prompt. Después de esto se crea un nuevo prompt al principio de la linea siguiente. Pero, ahora, el prompt no es GS>. Es G<1>. Esta nueva forma de prompt refleja el número de elementos en la pila de operandos. De modo que, si tu tienes GS<123> en cualquier momento en tu sesión ghostscript esto significa que hay 123 elementos en la pila de operandos. 

Puedes introducir más de un elemento en la pila de operandos de un solo paso. Para ello, debes teclear todos los elementos consecutivamente, pero separados por un espacio en blanco. Por ejemplo, si tu tecleas 1 2 3 4 5 6 en el prompt, los elementos 1, 2, 3, 4, 5, 6, se apilarán en la pila de operandos respectivamente. Si ejecutas pstack después de esto, entonces los elementos se visualizarán en orden vertical de forma que el último elemento introducido se visualiza primero. La visualización de esta sesión de dos comandos puede quedar como sigue: 

GS>1 2 3 4 5 6 G<6>pstack
6
5
4
3
2
1
G<6>

También es posible introducir elementos en la pila de operandos y ver el contenido de la pila en un solo paso. Todo lo que tienes que hacer es añadir el comando pstack después de los elementos a ser introducidos. Por tanto: 

GS>1 2 3 4 5 6 pstack6
5
4
3
2
1
G<6>

Hasta ahora hemos usado números para introducir elementos. Los números no son el único tipo de elementos, es posible introducir otros tipos de elementos como variables o claves, cadenas de texto, bloques, etc. Los trataremos más tarde en detalle. De todas maneras hay algo que debemos decir:  si intentas introducir por ejemplo, un solo caracter a o una cadena abc se emitirá un mensaje de error. Esto es debido a que PostScript no puede entender estas cosas. Si quieres introducir un caracter o una cadena tienes que encerrarlo mediante los símbolos (). Aquí hemos hablado también acerca de un tipo especial de elemento que se llama marktype. Para ver todo esto podemos dar la siguiente sesión de ejemplo: 

GS>1 2 3 mark 4 5 6 pstack6
5
4
-marktype-
3
2
1
G<7>

Ahora vamos a ver algunos ejemplos de las operadores que manipulan la pila de operandos. Daré una sesión para mostrar como actuan estos operadores y me gustaría cerrar esta sección sin más explicaciones. 

GS>1 2 3 mark 4 5 6 pstack6
5
4
-marktype-
3
2
1
G<7>pop pstack
5
4
-marktype
3 
2
1
G<6>exch pstack
4
5
-marktype
3
2
1
G<6>dup pstack
4
4
5
-marktype-
3
2
1
G<7>2 copy pstack
4
4
4
4
5
-marktype
3
2
1
G<9>5 index pstack
-marktype-
4
4
4
4
5
-marktype
3
2
1
G<10>cleartomark cleartomark pstack
3
2
1
G<3>3 1 roll pstack
2
1
3
G<3>count pstack
3
2
1
3
G<4>mark 7 8 pstack
8
7
-marktype-
3
2
1
3
G<7>counttomark pstack
2
8
7
-marktype-
3
2
1
3
G<8>clear pstack
GS>

Operadores matemáticos

Aparte de los operadores de manipulación de la pila de operandos de PostScript hay algunos operadores aritméticos y matemáticos. Más abajo se dan estos operadores. No habrá ejemplos. Esto se deja en manos del lector que debería ser capaz de crearlos, después de haber estudiado las sesiones de ejemplo de arriba.

add:
Este comando necesita dos parámetros numéricos cuyos valores se suman. Si llamamos m y n a estos valores, entonces el comando sería m n add. Al ejecutarlo se introducen primero m y después n en la pila de operandos. La fase final es al ejecución del operador add sobre los dos operandos de la cima de la pila. Esto crea un nuevo elemento cuyo valor es la suma de m y n. Una vez finalizada la operación m y n desaparecen de la pila. En su lugar, el resultado llega a ser el elemento de la cima de la pila de operandos.
div:
Este comando necesita dos parámetros numéricos que serán los que se usarán en la operación de división. Sean estos parámetros, m y n, la instrucción sería m n div. La mecánica de la operación es la misma que la de la operación add. La operación de división trabaja a nivel de aritmética de punto flotante. Después de que finaliza la operación solo queda en la pila de operandos el resultado de la operación de división como un nuevo elemento. m y n desaparecen.
idiv:
Este comando necesita dos parámetros numéricos que se usarán en la operación de división entera. Sean estos parámetros, m y n, la instrucción sería m n idiv. Todo funciona como en el caso de div excepto por la división misma. En este caso se trata de una división que funciona en el nivel de la aritmética entera. También funcionará aunque los parámetros no sean enteros.
mod:
Este comando necesita dos parámetros enteros. Obtiene el resto de dividir el primer parámetro entre el segundo. Si cualquiera de los parámetros no es entero la operación falla. Al final lo único que queda en la pila de operandos es el resultado de la operación, no los parámetros.
mul:
Igual que add, div. Es un operador binario que necesita dos valores numéricos. El resultado es la multiplicación de los parámetros y se mantiene en la pila de operandos como un nuevo elemento.
sub:
Igual que add, div, mul. La única diferencia es el tipo de operación. En operador resta el valor del segundo parámetro del valor del primero. Tanto los parámetros como el resultado son valores numéricos y el resultado queda en la pila de operandos después de que la operación ha finalizado.
exp:
Este es un operador matemático binario. Necesita dos parámetros. El primero es la base y el segundo el exponente. Eleva el valor de la base a la potencia cuyo valor es el exponente. Los parámetros deben estar dentro de los límites de la operación de exponenciación. El resultado es un número en punto flotante que queda como un nuevo elemento de la pila de operandos.
atan:
Este es otro operador matemático binario, en este caso para evalúa un ángulo. El ángulo se da en grados entre 0 y 360. Se necesitan dos parámetros. La razón del primer parámetro al segundo es igual a la tangente del ángulo a ser evalúado. Cualquiera de los parámetros puede ser 0 pero no ambos. Los signos de los parámetros determinan el cuadrante donde el resultado yace. Los valores positivos en el primer parámetro corresponden a planos y positivos. Por otro lado, los valores positivos en el segundo parámetro indican planos x positivos.
abs:
Este es un operador matemático unario. Necesita un solo parámetro cuyo valor absoluto es el resultado de la operación. De forma similar a lo visto arriba, el resultado permanece en la pila como un nuevo elemento.
neg:
Cambia el signo de su único parámetro. Es un operador aritmético unario.
ceiling:
Es un operador unario cuyo valor es el entero más cercano por arriba al parámetro que recibe.
floor:
Es un operador unario cuyo valor es el entero más cercano por abajo al parámetro que recibe.
round:
Es un operador unario cuyo valor es el entero más cercano al parámetro que recibe.
truncate:
Es un operador unario que elimina la parte decimal de su parámetro.
sqrt:
Es un operador unario cuyo valor es la raíz cuadrada (square root) de su parámetro.
cos:
Es un operador unario cuyo valor es el coseno de su parámetro. El parámetro debe estar en grados.
sin:
Es un operador unario cuyo valor es el seno de su parámetro. El parámetro debe estar en grados.
ln:
Es un operador unario cuyo valor es el logaritmo natural de su parámetro.
log:
Es un operador unario cuyo valor es el logaritmo en base 10 de su parámetro.

Antes de terminar este artículo una nota más. Si bien se ha mencionado arriba, quizás de forma implícita, los parámetros (operandos en la terminología PostScript) de un comando pueden crear algunos problemas desagradables. El comando (u operador en la terminología PostScript) busca sus parámetros en la pila de operandos. Cuando se encuentran el comando los usa y son borrados de la pila de operandos. De manera que ejecutar, a propósito o por error, un comando que necesita parámetro(s) sobre una pila de operandos sin valores para ellos, puede provocar bien una notificación sobre los parámetros que están el cima de la pila si estos no son válidos para el tipo de parámetro requerido, o que alguno(s) de los elementos de la pila de operandos sean eliminados. Por tanto el usuario debe tener mucho cuidado con esto.

Antes de finalizar esta presentación recomendamos escribir programas más complicados y completos a los usuarios que quieran avanzar con el lenguaje PostScript. Todas las preguntas y comentarios son bienvenidos.