miércoles, 13 de febrero de 2013

Lenguas Muertas I - Yoda Programa

Creo que debe ser uno de los fanáticos de Star Wars más jóvenes que conozco. Con sólo tres años y medio, ya vió toda la saga y sigue viendo algunos fragmentos de sus episodios favoritos, como el enfrentamiento el primer enfrentamiento de Qui-Gon Jinn y Obi Wan Kenobi contra los droides en la nave de la federación de comercio en Episodio 1 o el escape de Luke Skywalker y sus amigos del pozo de Carkoon , con su frase “Jabba...es tu última oportunidad...libéranos o muere...” en Episodio 6. 

Entre sus personajes favoritos están Obi Wan y Anakin Skywalker antes de ‘hacerse malo. Aunque también le cae simpático Yoda. Tal vez porque se ve representado por el tamañoo tal vez porque le resulta simpática esa forma especial que el maestro Jedi tiene de hablar utilizando estructuras gramaticales compuestas con verbo , sujeto y modificadores directos, de modo tal que suele decir frases como  “ir tu debes”.

Este hablar “alrevés” del maestro Yoda me lleva a asociarlo con un lenguaje de programación puesto en escena a principios de los ‘70 y que no pudo proyectar una posición más allá de mediados de los ‘80. Se trata del Forth, creado por el físico Charles Moore con el objeto de controlar el posicionamiento de los telescopios de su lugar de trabajo, el National Radio Astronomy Observatory of Arizona.

El origen de su nombre tiene dos raíces, por un lado de una simplificación de la palabra fourth que aludía a un lenguaje destinado a las computadoras de cuarta generación, es decir, aquellas que adoptaron los primeros circuitos integrados en su construcción, y por otro, del sistema operativo de la máquina IBM 1131 en dónde se compiló el primer entorno, que contaba sólo con cinco caracteres para los nombres de los archivos. Por esta limitante, el archivo compilado se llamó FORTH.

Forth es un lenguaje imperativo, de nivel medio y sus implementaciones consisten en una consola de comandos y un compilador interactivo con el que se puede extender el lenguaje, creando nuevas palabras, que serían el equivalente a rutinas o funciones en otros lenguajes. Esta arquitectura recuerdo un poco a la de Smalltalk, en donde es posible definir e interactuar con los objetos que viven en el entorno. 

Pero volviendo a Forth, digamos que siempre estuvo pensado para interactuar con pocos recursos de hardware y de hecho, para interactuar con dispositivos pequeños y medianos en forma embebida. Hasta principios de los ‘90, por ejemplo, Federal Express utilizó un dispositivo denominado SuperTracker, con un firmware desarrollado en Forth,  para registrar encomiendas guardando los ID escaneados en una RAM y luego sincronizando contra una computadora central regional. Otro uso de Forth tuvo lugar en un proyecto de plataforma para la creación de Smartcards en Europa, en 1995, llamado Open Terminal Architecture. Pero hay más ejemplos de uso que pueden encontrarse en esta dirección.

Esa gramática distintiva de Forth está dada por la estructura de pila de datos con que operan todas sus palabras, puesto que no existe el pasaje de parámetros ni los retornos de valores sino que son tomados y almacenados en esta estructura. Recordemos que como toda pila, por ejemplo la de platos lavados, el primer elemento a guardar, será el último plato que se lavó.

Utilizar esta metodología para cálculos, nos brinda el sistema con notación postfija que también es conocido como notación polaca inversa y que se utiliza en las calculadoras Hewlett-Packard. Recordemos que con este sistema, el uso de paréntesis en las expresiones algebraicas es innecesario. Supongamos, por ejemplo, que en una planilla de cálculos ingresamos la siguiente cuenta:

3 x (5 + 15)

El resultado es 60. Pero si ahora lo quisiéramos calcular con nuestra HP-48GX, deberíamos ingresar:

3 5 15 + *

Y deberíamos interpretar de la siguiente manera: apilar los números 3, 5, y 15, sumar los últimos dos números ingresados (5 + 15) y resultado dejado en pila, multiplicarlo con el primer número. Más gráficamente:

P1            P2            P3
*
+            *
15    =>        20        =>    60
5            3
3

Volviendo al primer cálculo hecho con nuestra planilla, si no hubiesemos utilizamos paréntesis, el resultado sería otro, puesto que la suma separa los términos: 3x5 =15 + 15 = 30

Con el ejemplo anterior en mente, estamos más o menos en condiciones de aceptar que las palabras en Forth, consumen sus argumentos de la pila (es decir, los sacan), hacen lo que tienen que hacer y finalmente dejan en la estructura el valor resultante. Veamos por ejemplo, cómo escribir una estructura condicional:

3 4 < IF .“ TRES es menor que CUATRO” ELSE .“ TRES es mayor o igual a CUATRO” THEN;

A no alterarse! Pensemos en la pila! Se ingresan los operandos 3 y 4. Luego se aplica la palabra “<”, es decir 3 y 4 son los argumento del operador lógico <. El resultado de la operación es 0 -porque representa a TRUE-  va a parar al tope de pila. Este valor es el argumento del IF,  y por ser verdadero, ejecuta lo que está antes del ELSE, en este caso imprime -es lo que hace el punto- el literal entre comillas. Lo que está luego del ELSE es opcional y en este caso particular, nunca se ejecutará y sólo aparece para mostrar la estructura completa que finaliza con THEN

Y qué pasaría con un ciclo definido? Bueno, si quisiéramos imprimir los primeros diez números naturales, podríamos escribir:

11 1 do . I loop;

Aqui, el 11 y el 1 se alojan en la pila y este último valor pasa a ser el valor inicial del ciclo que deberá iterar y ejecutar el contenido diez veces (en la vuelta once terminaría). Notar la aparición de I, que es una variable implícita del ciclo y conserva el valor del número de iteración, que en este caso, se está imprimiendo. Y por supuesto, el ciclo termina con loop.

Esto, como suele decirse, es sólo la punta del iceberg y en caso de interés, se puede extender el tema visitando Forth o leyendo Thinking in Forth. En mi caso, ambos recursos fueron bastante efectivos y gracias a ellos pude escribir mi primer programa Forth.

Para aquellos nostálgicos que quisieran probar el lenguaje en un ambiente más adecuado a su época de esplendor, podemos decir que prácticamente todas las home computers tuvieron -tienen- su versión de Forth, siendo el máximo exponente la Jupiter Ace de la empresa Jupiter Cantab LTD.
Esta empresa, que fuera fundada por dos ex miembros de Sinclair integrantes del equipo desarrollo de la ZX Spectrum, Richard Altwasser y Stephen Vickers, construyeron una computadora de rasgos similares a la Sinclair ZX81 pero varias distinciones:: poseía un gabinete de color blanco, con un teclado de goma, generador de sonido similar al de Spectrum y 3Kb de RAM, todo dirigido por un microprocesador Z80. Pero el rasgo más sobresaliente resultó ser el entorno Forth que incorporaba en ROM, al contrario de la tendencia de la época de utilizar BASIC. Los programas construidos en Forth se ejecutaban tres veces más rápido que su equivalente en BASIC, pero debido a la dificultad de aprendizaje, la Jupiter Ace tuvo muy poca aceptación de mercado y en sus dos años de producción, se crearon cerca de 8000 unidades.

Antes de terminar, quisiera dejar el listado de mi primer programa Forth. Se trata de un pequeño juego que suelo escribir en distintos sistemas / lenguajes que cae en mis manos, como una alternativa al tradicional “Hola Mundo”. Consiste en un juego de adivinanza, en dónde la computadora selecciona aleatoriamente un número del uno al diez y el usuario cuenta con tres posibilidades para adivinarlo. En cada intento fallido, el programa ayuda informando si es número elegido es mayor o menor al ingresado.
El programa fue escrito en Win32Forth, aunque podría correr en la versión online jsForth. Está dividido en tres secciones: la primera contiene una declaración de variables y constantes, que también dispone el lenguajes aunque su uso no es tan directo puesto que para almacenar o recuperar los valores es necesario hacerlo a través de la pila. En segundo lugar, se definen una palabra para controlar el acceso desde teclado del intento del usuario, que se representa mediante una cadena de caracteres. Éstas, son operadas de manera similar al lenguaje C mediante utilización de punteros que, aunque, las referencias se hacen a través de la pila.

Dado que no existe en Forth un método nativo para elegir valores al azar, hay que definir algún método, como por ejemplo, la congruencia lineal implementada en tercer lugar mediante la definición de la palabra RANDOMN. Por último, la cuarta sección contiene el código de la palabra ADIVINA que dirige la ejecución del programa en sí.

Ahora es momento de dejar de hablar de lenguas muertas y volver al rol de padre, mi hijo Ian, el pequeño fanático de Star Wars, está reclamando una repetición de la pelea final de Episodio III.



http://www.forth.com/resources/apps/more-applications.html

http://www.drdobbs.com/open-source/smart-cards-and-the-open-terminal-archit/184410748



ADIVINA


3 CONSTANT INTENTOS

VARIABLE numero
VARIABLE vuelta
VARIABLE semilla

VARIABLE numero    ( Declaracion de variables)
VARIABLE vuelta   

HERE semilla !    ( la semilla arranca con el valor de la dirección de memoria)

: INPUT$ ( Palabra para efectuar input de hasta 2 caracteres)
         PAD 1+
         2 ACCEPT
         PAD C!
         PAD
;

: RANDOMN  ( Esta palabra recibe un valor limite de numeros aleatorios y actualiza la semilla)
        semilla @ 31421 * 6927 + DUP semilla ! swap mod
;


: ADIVINA
       
        CLS
       
        11 RANDOMN                    ( Numero al azar entre 0 y 10)

        numero !                    ( El valor elegido que quedó en el tope de pila y se guarda en la variable)
       
       
        CR ." Adiviná el numero que pensé, tenés " INTENTOS . ." intentos " cr
       
       
        1 vuelta !                                        ( Vuelta es 1)
       
        BEGIN
            cr ." Intento "  vuelta @ .  ." : "
           
            INPUT$ COUNT NUMBER?                        ( Input y conversión de cadena a entero)
            2DROP                                        ( Se tiran los flags de la conversión, queda en el tope el número ingresado)
           
            dup                                             ( Copia del número ingresado, para la siguiente comparación)
           
            numero @ <> IF  vuelta @ 1 + vuelta !  THEN  ( Si no se adivinó, se da una vuelta más)
           
        numero @ =   vuelta @ INTENTOS >  OR UNTIL         ( En pila está el numero ingresado. Se sale si el igual al elegido o si hay más de 3 vueltas)
       
        CR
         vuelta @ INTENTOS > IF ." PERDISTE! ERA EL " numero @ . ELSE ." ACERTASTE" THEN        ( Resultados)
        CR
;
       
   





,