PostScript II: La pila de operandos, manipulaciones y operadores matem'aticos
ArticleCategory:[Artikel Kategorie]
Software Development
AuthorImage:[Bild des Autors]
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]
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.