Su nombre es una contracción de la palabra inglesa fourth, dado que sus creadores le consideraban destinado a la cuarta generación de computadoras, pero la primera edición del lenguaje fue preparada para un IBM 1130, que solo permitía nombres con una longitud máxima de cinco letras; su nombre se quedó ya para siempre en FORTH. Forth es deletreado a veces con todas las letras en mayúsculas siguiendo el uso acostumbrado durante los primeros años, aunque el nombre no es un acrónimo.
Inicialmente diseñado para una aplicación muy concreta, la astronomía (cálculo de trayectorias de cuerpos en órbita, cromatografías, análisis de espectros de emisión), ha evolucionado hasta ser aplicable a casi todos los demás campos relacionados o no con esa rama de la ciencia (cálculos de probabilidad, bases de datos, análisis estadísticos y hasta financieros).
Posteriormente, un programa para la adquisición automática y continua de datos realizado en este lenguaje ha descubierto al menos la mitad de los cúmulos interestelares conocidos en la actualidad.
Forth es un lenguaje de programación de computadoras procedimental, estructurado, imperativo, reflexivo, basado en pila y sin comprobación de tipos. Forth ofrece tanto la ejecución interactiva de comandos (haciéndolo conveniente como shell para los sistemas que carecen de un sistema operativo más formal) como la capacidad de compilar secuencias de comandos para la ejecución posterior. Algunas implementaciones del Forth (usualmente las versiones tempranas o las escritas para ser extremadamente portable) compilan código enhebrado (threaded code), pero muchas implementaciones de hoy generan código de máquina optimizado como otros compiladores de lenguajes.
Una de sus importantes características es la utilización de una pila de datos para pasar los argumentos entre las palabras, que son los constituyentes de un programa en Forth.
Aunque no es tan popular como otros sistemas de programación, Forth tiene suficiente soporte para mantener varios vendedores y contratistas lenguaje en el negocio. Forth es usado actualmente en cargadores (boot loaders) tales como Open Firmware, aplicaciones espaciales,[1] y otros sistemas empotrados. Una implementación de Forth por el Proyecto GNU es activamente mantenida, y su último lanzamiento fue en noviembre de 2008. El estándar de 1994 está actualmente siendo sometido a revisión, llamado provisionalmente Forth 200x.[2]
Visión general
Un ambiente Forth combina el compilador con una shell interactivo. El usuario interactivamente define y corre subrutinas, o «palabras», en una máquina virtual similar al ambiente de runtime. Las palabras pueden ser probadas, redefinidas, y depuradas a medida que el código fuente es ingresado sin recompilar o reiniciar el programa entero. Todos los elementos sintácticos, incluyendo las variables y los operadores básicos, aparecen como tales procedimientos (en forma de palabras). Incluso si una particular palabra es optimizada para no requerir una llamada de subrutina, todavía sigue también disponible como subrutina. Por otro lado, la shell puede compilar comandos interactivamente mecanografiados en código de máquina antes de correrlos. (Este comportamiento es común, pero no requerido). Los ambientes Forth varían en cómo es almacenado el programa resultante, pero idealmente, correr el programa tiene el mismo efecto que entrar manualmente el código fuente de nuevo. Esto contrasta con la combinación de C con los shells de UNIX, en donde las funciones compiladas son una clase especial de objetos de programa y los comandos interactivos son estrictamente interpretados [cita requerida]. La mayor parte de las características únicas de Forth resultan de este principio. Al incluir la interacción, el scripting, y la compilación, Forth fue popular en los computadores con recursos limitados, tales como el BBC Micro y las series del Apple II, y permanece así en aplicaciones tales como firmware y pequeños microcontroladores. Donde los compiladores C ahora pueden generar código más compacto y con mejor desempeño, Forth conserva la ventaja de la interactividad.[cita requerida]
Las pilas
Cada ambiente de programación con subrutinas implementa una pila para el flujo de control. Esta estructura típicamente también almacena las variables locales, incluyendo los parámetros de la subrutina (en un sistema de llamada por valor como en C). Con frecuencia, sin embargo, Forth no tiene variables locales, ni es llamado-por-valor. En lugar de eso, los valores intermedios son mantenidos en una segunda pila. Las palabras operan directamente en los valores superiores de esta pila. Por lo tanto, puede ser llamada la pila de «parámetro» o de «datos», pero es más conocida como la «pila». La pila de llamada de funciones es entonces llamada la pila de retorno o de «encadenamiento» ( en inglés linkage o return stack), abreviado rstack. Las funciones especiales de manipulación del rstack proporcionadas por el núcleo permiten que sea usado para el almacenamiento temporal dentro de una palabra, pero no puede ser usado de otra manera para pasar parámetros o para manipular datos.
La mayoría de las palabras son especificadas en términos de su efecto sobre la pila. Típicamente, los parámetros son colocados en el tope de la pila antes de que la palabra se ejecute. Después de la ejecución, los parámetros son borrados y substituidos por valores de retorno. Para los operadores aritméticos, esto sigue la regla de la notación polaca inversa. Ver abajo para los ejemplos que ilustran el uso de la pila.
Mantenimiento
Forth es un lenguaje simple y extensible; su modularidad y extensibilidad permiten la escritura de programas de alto nivel tales como sistemas de CAD. Sin embargo, la extensibilidad también ayuda a que programadores pobres escriban código incomprensible, que ha dado a Forth una reputación como «lenguaje de solo escritura». Forth ha sido usado con éxito en proyectos grandes y complejos, mientras que las aplicaciones desarrolladas por profesionales competentes y disciplinados han probado ser de fácil mantenimiento en plataformas de hardware cambiantes durante décadas de uso.[3] Forth tiene un nicho tanto en aplicaciones astronómicas como espaciales.[4] Todavía hoy, Forth es usado en muchos sistemas empotrados (pequeños dispositivos computarizados), debido a su portabilidad, uso eficiente de la memoria, corto tiempo de desarrollo, y rápida velocidad de ejecución. Ha sido implementado eficientemente en procesadores RISC modernos, y han sido producidos procesadores que usan Forth como lenguaje de máquina.[5] Otros usos de Forth incluyen Open Firmware, boot ROMs usadas por Apple, IBM, Sun, y OLPC XO-1; y la primera etapa del controlador de arranque basada en FICL del sistema operativo FreeBSD.
Historia
Forth se desarrolló a partir del sistema de programación personal de Charles H. Moore, que había estado en desarrollo continuo desde 1958.[6]
Forth fue expuesto por primera vez a otros programadores a principios de los años 1970, comenzando con Elizabeth Rather en el National Radio Astronomy Observatory de los Estados Unidos.[6] Después de su trabajo en NRAO, Charles Moore y Elizabeth formaron Forth, inc. en 1973, refinando y portando sistemas Forth a docenas de otras plataformas en la siguiente década.
Forth fue nombrado así porque en 1968 «el archivo conteniendo el interpretador fue etiquetado FOURTH, por la 4.ª (siguiente) generación de software - pero el sistema operativo del IBM 1130 restringía los nombres de archivo a 5 caracteres».[7]
Moore vio a Forth como el sucesor de compilar-encadenar-ejecutar de los lenguajes de tercera generación, o software para hardware «de cuarta generación», no en el sentido de un lenguaje de programación de cuarta generación como ha venido a ser usado el término.
Debido a que Charles Moore se había trasladado con frecuencia de un trabajo a otro en su carrera, una presión temprana en el lenguaje de desarrollo era la facilidad de portarlo a diversas arquitecturas de computadora. Un sistema Forth ha sido usado con frecuencia para «levantar» un nuevo hardware. Por ejemplo, Forth fue el primer software residente en el nuevo chip Intel 8086 en 1978 y MacFORTH era el primer sistema de desarrollo residente para el primer Apple Macintosh en 1984.[6]
Comenzando en 1976, el microFORTH de Forth inc. fue desarrollado para los microprocesadores Intel 8080, Motorola 6800, y el Zilog Z80. MicroFORTH fue usado después por aficionados para generar sistemas Forth para otras arquitecturas, tales como los MOS 6502 de 1978. La amplia diseminación finalmente llevó a la estandarización del lenguaje. La práctica común era codificada en los estándares de facto de FORTH-79[8]
y FORTH-83[9]
de los años 1979 y 1983, respectivamente. Estos estándares fueron unificados por el ANSI en 1994, comúnmente referenciado como ANS Forth.[10]
Forth llegó a ser muy popular en los años 1980 porque estaba bien adaptado a los pequeños microcomputadores de ese tiempo, pues es compacto y portable. Por lo menos un computador personal, el Jupiter Ace británico, tenía a Forth en su sistema operativo residente en ROM. El Canon Cat también usaba Forth para su programación de sistema. Rockwell también produjo los microcomputadores en un simple chip, el R65F11 y el R65F12, con núcleos Forth residentes.
Forth confía fuertemente en el uso explícito de una pila de datos y de la notación polaca inversa (RPN o notación postfija, comúnmente usada en calculadoras de Hewlett-Packard. En RPN, el operador es colocado después de sus operandos, a diferencia de la más común notación infija donde es colocado entre los operandos. La notación postfija hace al lenguaje más fácil analizar gramaticalmente (parse) y extender; Forth no usa una gramática BNF, y no tiene un compilador monolítico. Extender el compilador solo requiere la escritura de una nueva palabra, en vez de modificar una gramática y de cambiar la implementación subyacente.
Usando RPN, se puede conseguir al resultado de la expresión matemática (25 * 10 + 50) de esta manera:
25 10 * 50 + .
300 ok
Esta línea de comando primero pone los números 25 y 10 en la pila implicada.
La palabra * multiplica los dos números en el tope de la pila y los sustituye por su producto.
Entonces el número 50 se pone en la pila.
La palabra + lo agrega al producto anterior. Finalmente, el comando . imprime el resultado al terminal de usuario.[11]
Incluso las características estructurales del Forth son basadas en la pila. Por ejemplo:
: FLOOR5 ( n -- n' ) DUP 6 < IF DROP 5 ELSE 1 - THEN ;
Este código define una nueva palabra llamada FLOOR5 usando los comandos siguientes (otra vez, «palabra» es el término usado para una subrutina):
DUP duplica el número en la pila;
< compara 6 con el número superior en la pila y los substituye por un valor verdadero-o-falso;
IF toma un valor verdadero-o-falso y elige ejecutar comandos inmediatamente después de él o saltar al ELSE;
DROP desecha el valor en la pila;
y THEN termina la condicional.
El texto entre paréntesis es un comentario, advirtiendo que esta palabra espera un número en la pila y retornará un número posiblemente cambiado. La palabra FLOOR5 es equivalente a esta función escrita en el lenguaje de programación C:
int floor5(int v) { return v < 6 ? 5 : v - 1; }
Esta función se escribe más sucintamente como:
: FLOOR5 ( n -- n' ) 1- 5 MAX ;
Se puede correr esta palabra como sigue:
1 FLOOR5 .
5 ok
8 FLOOR5 .
7 ok
Primero el interpretador empuja (push) un número (1 u 8) sobre la pila, después llama a FLOOR5, que retira (pop) este número otra vez y empuja el resultado. Finalmente, una llamada a «.» retira el resultado de la pila y lo imprime al terminal del usuario.
Facilidades
El analizador sintáctico (parser) de Forth es simple, puesto que no tiene una gramática explícita. El interpretador lee una línea de entrada desde un dispositivo de entrada de usuario, la cual es entonces analizada sintácticamente para una palabra usando los espacios como delimitadores; algunos sistemas reconocen caracteres de espacio en blanco adicionales. Cuando el interpretador encuentra una palabra, intenta encontrar la palabra en el diccionario. Si la palabra es encontrada, el interpretador ejecuta el código asociado con la palabra, y después retorna para analizar (parse) el resto del flujo de entrada (stream). Si la palabra no es encontrada, se asume que la palabra es un número, y se hace una tentativa de convertirlo el texto que lo representa en un número y de empujarlo (push) en la pila; si se tiene éxito, el interpretador continúa analizando el flujo de entrada. De lo contrario, si las operaciones de búsqueda de la palabra y la conversión del número fallan, el interpretador imprime la palabra seguida por un mensaje de error indicando que la palabra no es reconocida, se limpia (flush) el flujo de entrada, y se espera la nueva entrada del usuario.[12]
La definición de una nueva palabra comienza con la palabra : (dos puntos) y finaliza con la palabra ; (punto y coma). Por ejemplo:
: X DUP 1+ . . ;
Esto compilará la palabra X, y hace el nombre hallable en el diccionario. Cuando es ejecutada al mecanografiar, por ejemplo, 10 X en la consola esto imprimirá 11 10.[13]
La mayoría de los sistemas Forth incluyen un ensamblador especializado que produce palabras ejecutables. El ensamblador es un dialecto especial del compilador. Los ensambladores Forth frecuentemente usan una sintaxis polaca inversa en la cual los parámetros de una instrucción preceden a la instrucción. El diseño usual del ensamblador Forth es para construir la instrucción en la pila, después la copia en memoria como el paso pasado. Los registros pueden ser referidos por el nombre usado por el fabricante, numerado (0..n, según lo usado en el código de operación real) o nombrado para su propósito en el sistema Forth: ej. «S» para el registro usado como puntero de la pila.[14]
Sistema operativo, los archivos y la multitarea
Los sistemas Forth clásicos tradicionalmente no usan ni el sistema operativo ni el sistema de archivos. En lugar de almacenar el código en archivos, el código fuente es almacenado en bloques escritos a direcciones físicas del disco. La palabra BLOCK es empleada para traducir el número de un bloque de disco de 1 KB de tamaño hacia la dirección de un buffer que contiene los datos, el cual es manejado automáticamente por el sistema Forth. Algunos sistemas implementan archivos de disco contiguos usando el acceso al disco del sistema, donde los archivos están situados en los rangos de bloques de disco fijos. Usualmente éstos se implementan como registros binarios de longitud fija, con un número entero de registros por bloque del disco. Una búsqueda rápida es alcanzada por el acceso hash en los datos clave.
La multitarea, (más comúnmente por planificación Round-robin cooperativa), está normalmente disponible (aunque las palabras multitarea y el soporte no son cubiertos por el estándar del ANSI Forth). La palabra PAUSE es usada para guardar el contexto de ejecución de la tarea actual, para localizar la siguiente tarea, y restaurar su contexto de ejecución. Cada tarea tiene sus propias pilas, copias privadas de algunas variables de control y un área de scratch. Como resultado, el intercambio de tareas es simple y eficiente, Las multitareas del Forth están disponibles incluso en los microcontroladores muy simples tales como el Intel 8051, Atmel AVR, y TI MSP430.[15]
Por contraste, algunos sistemas Forth corren bajo un sistema operativo anfitrión como Microsoft Windows, Linux o una versión de UNIX y usan el sistema de archivos del sistema operativo anfitrión para los archivos de fuente y de datos; el estándar ANSI Forth describe las palabras usadas para la entrada-salida. Otras facilidades no estándar incluyen un mecanismo para hacer llamadas al SO o al sistema de ventanas anfitrión, y muchos proporcionan extensiones que emplean la previsiones proporcionadas por el sistema operativo. Típicamente tienen un conjunto más grande y diferente de palabras que la palabra por defecto PAUSE del Forth, para la creación, suspensión, destrucción y modificación de prioridad de la tarea.
Autocompilación y compilación cruzada
Un sistema Forth con todas las facilidades, con todo el código fuente, se compilará a sí mismo, con una técnica comúnmente llamada por los programadores Forth como metacompilación (aunque el término no equivale exactamente a la metacompilación como se define normalmente). Usualmente el método consiste en redefinir un puñado de palabras que ponen bits compilados en la memoria. Las palabras del compilador usan versiones especialmente nombradas de fetch y store que son redireccionadas a un área de buffer en memoria. El área del buffer simula o accesa un área de memoria comenzando en una dirección diferente que el buffer de código. Tales compiladores definen palabras para acceder tanto a la memoria del computador destino como la memoria del computador anfitrión (compilación).[16]
Después de que las operaciones de fetch y store son redefinidas para el espacio del código, el compilador, ensamblador, etc. son recopilados usando la nueva definición de fetch y store. Esto efectivamente rehúsa todo el código del compilador y del interpretador. Entonces, el código del sistema Forth es compilado, pero esta versión es almacenada en el buffer. El buffer en memoria es escrito al disco, y se proporcionan las maneras de cargarlo temporalmente en la memoria para pruebas. Cuando la nueva versión parece trabajar, se escribe sobre la versión previa.
Hay numerosas variaciones de tales compiladores para diversos ambientes. Para los sistemas embebidos, el código puede ser escrito en otro computador, una técnica conocida como compilación cruzada, sobre un puerto serial o aún por un solo bit TTL, mientras se mantienen los nombres de las palabras y otras partes no ejecutables del diccionario en la computadora de compilación original. Las definiciones mínimas para este compilador Forth son las palabras fetch y store para un byte, y la palabra que ordena sea ejecutada una palabra de Forth. Con frecuencia la parte que consume más tiempo de escribir un puerto remoto es construir el programa inicial para implementar fecth, store y execute, pero muchos microprocesadores modernos tienen características de depuradores integrados (tales como el Motorola CPU32) que eliminan esta tarea.[17]
Estructura del lenguaje
La estructura básica de datos de Forth es el «diccionario» que mapea «palabras» a código ejecutable o a estructuras de datos con nombre. El diccionario descansa en la memoria como árbol de lista encadenada con los enlaces procediendo desde la última palabra definida (la más reciente) hasta la más antigua, hasta que es encontrado un centinela, usualmente un puntero NULL. Un cambio de contexto causa que la búsqueda de la lista comience en una hoja diferente y la búsqueda de la lista encadenada continúa de tal manera que la rama se combina en el tronco principal de nuevo dirigiéndose finalmente al centinela (NULL), la raíz (en raros casos como en meta-compilación el diccionario puede estar aislado, hay varios). El efecto es un uso sofisticado de espacio de nombres (namespaces) y críticamente puede tener el efecto de sobrecargar palabras claves, el significado es contextual.
Una palabra definida generalmente consiste en un encabezado (head) y un cuerpo (body), con el encabezado consistiendo en el name field (NF) y el link field (LF) y un cuerpo consistiendo del code field (CF) y el parameter field (PF).
El encabezado y al cuerpo de una entrada de diccionario son tratados separadamente porque ellos pueden no estar contiguos. Por ejemplo, cuando un programa de Forth es recompilado para una nueva plataforma, el,encabezado puede quedar en el computador de compilación, mientras que el cuerpo va a la nueva plataforma. En algunos ambientes (tales como sistemas empotrados) los encabezados ocupan memoria innecesariamente. Sin embargo, algunos compiladores cruzados pueden poner las cabezas en el computador destino si se espera que este computador soporte un sistema Forth interactivo.[18]
Entrada de diccionario
El formato exacto de una entrada de diccionario no está prescrito, y las implementaciones varían. Sin embargo, ciertos componentes casi siempre están presentes, aunque el tamaño exacto y la orden pueden variar. Descrito como estructura, una entrada de diccionario pudo verse así:[19]
structure
byte: flag \ 3bit flags + length of word's name
char-array: name \ name's runtime length isn't known at compile time
address: previous \ link field, backward ptr to previous word
address: codeword \ ptr to the code to execute this word
any-array: parameterfield \ unknown length of data, words, or opcodes
end-structure forthword
El campo nombre comienza con un prefijo que da la longitud del nombre de la palabra (típicamente hasta 32 bytes), y varios bits para los flags. Entonces, la representación de caracteres del nombre de la palabra sigue al prefijo. Dependiendo de la implementación particular del Forth, puede haber para alineación, uno o más bytes NUL (« \0 »).
El campo link contiene un puntero a la palabra previamente definida. El puntero puede ser un desplazamiento relativo o una dirección absoluta que apunta al hermano anterior.
El puntero del campo del código será: o la dirección de la palabra que ejecutará el código, o datos en el campo del parámetro, o el principio del código de máquina que el procesador ejecutará directamente. Para las palabras definidas por la palabra «dos puntos» :, el puntero del campo del código apunta a la palabra que guardará el puntero de instrucción actual (IP) de Forth en la pila de retorno, y carga el IP con la nueva dirección desde la cual continuar la ejecución de palabras. Esto es lo mismo que lo que hacen las instrucciones call/return del procesador.
Estructura del compilador
El compilador en sí mismo consiste de palabras Forth visibles al sistema, no es un programa monolítico. Esto permite que un programador cambie las palabras del compilador para propósitos especiales.
El flag de «tiempo de compilación» en el campo nombre es ajustado para las palabras con comportamiento en «tiempo de compilación». La mayoría de las palabras simples ejecutan el mismo código si están mecanografiadas en una línea de comandos, o insertadas en otro código. Al compilar éstas, el compilador simplemente coloca el código o un puntero enhebrado (threaded pointer) hacia la palabra.[13]
Los ejemplos clásicos de palabras de tiempo de compilación son las estructuras de control, como por ejemplo IF y WHILE. Todas las estructuras de control de Forth, y casi todo su compilador son implementados como palabras de tiempo de compilación. Todas las palabras de flujo de control de Forth son ejecutadas durante la compilación para compilar varias combinaciones de las palabras primitivas BRANCH y ?BRANCH (branch y branch if false). Durante la compilación, la pila de datos es usado para soportar el balanceo, anidado, y backpatching de las direcciones de bifurcación de las estructuras de control. El pequeño código de ejemplo:
... DUP 6 < IF DROP 5 ELSE 1 - THEN ...
será compilado como la siguiente secuencia dentro de una definición:
Los números después de BRANCH representan direcciones relativas de saltos (jump). LIT es la palabra primitiva para empujar (push) un número «literal» sobre la pila de datos.
Estado de compilación y estado de interpretación
La palabra : (dos puntos) analiza sintácticamente (parse)un nombre como parámetro, crea una palabra (una definición de «dos puntos») y entra en el estado de compilación. El intérprete continúa leyendo palabras delimitadas por espacio desde el dispositivo de entrada del usuario. Si una palabra es encontrada, el intérprete ejecuta la semántica de compilación asociada a la palabra, en vez de la semántica de interpretación. Por defecto la semántica de compilación de una palabra es añadir su semántica de interpretación a la definición actual.[13]
La palabra ; (punto y coma) finaliza la definición actual y retorna al estado de interpretación. Ella es un ejemplo de una palabra cuya semántica de compilación difiere de la que se tiene por defecto. La semántica de interpretación de ; (punto y coma), la de la mayoría de las palabras de flujo de control, y la de algunas otras palabras están indefinidas en ANS Forth, lo que significa que ellas solo deben ser usadas dentro de definiciones y no en la línea interactiva de comando.[13]
El estado del intérprete puede ser cambiado manualmente con las palabras [ y ] (corchete izquierdo y corchete derecho) entran en el estado de interpretación o en el estado de compilación, respectivamente. Estas palabras pueden ser usadas con la palabra LITERAL para calcular un valor durante una compilación e insertarlo en la actual definición de dos puntos. El LITERAL tiene la semántica de compilación para tomar un objeto de la pila de datos y añadir la semántica a la definición actual de dos puntos para poner ese objeto en la pila de datos.
En ANS Forth, el estado actual del intérprete puede ser leído desde el flagSTATE que contiene el valor true cuando está en estado de compilación y false en caso contrario. Esto permite la implementación de palabras de estado inteligente con un comportamiento que cambia según el estado actual del intérprete.
Palabras inmediatas
La palabra IMMEDIATE marca la definición dos puntos más reciente como una palabra inmediata, reemplazando efectivamente su semántica de compilación por su semántica de interpretación.[20] Las palabras inmediatas son normalmente ejecutadas durante la compilación, no se compilan, pero esto puede ser sobreescrito por el programador, en cualquier estado. ; es un ejemplo de una palabra inmediata. En el ANS Forth, la palabra POSTPONE toma un nombre como un parámetro y añade la semántica de compilación de la palabra nombrada a la definición actual, incluso si la palabra era marcado inmediata. Forth-83 definió las palabras separadas COMPILE y [COMPILE] para forzar la compilación de palabras no-inmediatas e inmediatas, respectivamente.
Palabras sin nombre y tokens de ejecución
En ANS Forth, las palabras sin nombre pueden ser definidas con la palabra :NONAME (sin nombre) que compila las palabras siguientes hasta el próximo ; (punto y coma) y deja un token de ejecución en la pila de datos. El token de ejecución proporciona un manejador (handle) opaco para la semántica de compilación, similar a los punteros de función del lenguaje de programación C.
Los tokens de ejecución pueden ser almacenados en variables. La palabra EXECUTE toma un token de ejecución de la pila de datos y realiza la semántica asociada. La palabra COMPILE, (compila-coma) toma un token de ejecución de la pila de datos y añade la semántica asociada a la definición actual.
La palabra ' (comilla sencilla) toma el nombre de una palabra como parámetro, y retorna en la pila de datos, el token de ejecución asociado con esa palabra. En el estado de interpretación, ' RANDOM-WORD EXECUTE es equivalente a RANDOM-WORD.[21]
Analizando (parsing) palabras y comentarios
Las palabras : (dos puntos) y ' (comilla sencilla) son ejemplos de palabras que toman sus argumentos del dispositivo de entrada del usuario en vez de la pila de datos. Otro ejemplo es la palabra ( (paréntesis abierto) la cual lee e ignora las siguientes palabras hasta, e incluyendo, el paréntesis cerrado y es usada para poner comentarios. Similarmente, la palabra \ (barra de división hacia atrás) es usada para los comentarios que continúan hasta el extremo de la línea actual. ( (paréntesis abierto) y \ (barra de división hacia atrás) son palabras como el resto, y por ello tienen que estar separadas de lo que las sigue (en este caso el comentario) por al menos un espacio en blanco.
Estructura del código
En la mayoría de los sistemas Forth, el cuerpo de una definición de código consiste en lenguaje de máquina o una cierta forma de código enhebrado (threaded code). La Forth original que sigue el estándar informal del Forth Interest Group (FIG), es un Threaded Interpretive Language (TIL). Esto también es llamado código enhebrado indirecto (indirect-threaded code), pero el enhebrado directo (direct-threaded) y la subrutina de Forth también han llegado a ser populares en tiempos modernos. Los más rápidos Forth modernos usan enhebrado de subrutinas (subrutine threading), insertan palabras simples como macros, y realizan la optimización de peephole u otras estrategias de optimización para hacer el código más pequeño y más rápido.[22]
Objetos de datos
Cuando una palabra es una variable u otro objeto de datos, el CF apunta al código de tiempo de ejecución asociado con la definición de la palabra que lo creó. Una palabra de definición tiene un característico «comportamiento de definición» (creando una entrada de diccionario y posiblemente asignando e inicializando un espacio para los datos) y también especifica el comportamiento de una instancia de la clase de las palabras construidas por esta palabra de definición. Los ejemplos incluyen:
VARIABLE
Nombra una posición de memoria no inicializada, una localización de memoria de una celda. El comportamiento de la instancia de una VARIABLE retorna su dirección de localización en la pila.
CONSTANT
Nombra un valor (especificado como un argumento a la palabra CONSTANT). El comportamiento de la instancia retorna ese valor.
CREATE
Nombra una localización; el espacio puede ser asignado en esta localización, o puede ser fijado para contener un string u otro valor inicializado. El comportamiento de la instancia retorna la dirección del principio de este espacio de memoria.
Forth también proporciona una facilidad por la cual un programador puede definir las nuevas palabras de definición específicas a una aplicación, especificando tanto un comportamiento de la definición (en tiempo de compilación) como un comportamiento de la instancia (en tiempo de ejecución). Algunos ejemplos incluyen buffers circulares, bits con nombres en puertos de E/S, y arreglos automáticamente indexados.
Los objetos de datos definidos por estas palabras y similares, son globales en alcance. La función para variables locales proporcionada en otros lenguajes, en Forth es proporcionada por la pila de datos (aunque Forth también tiene variables locales reales). Comparado con otros lenguajes, el estilo de programación en Forth usa muy pocos objetos de datos con nombre; tales objetos de datos son usados típicamente para contener datos que son usados por un número de palabras o de tareas (en una implementación multitarea).[23]
Forth no hace cumplir la consistencia en el uso de tipos de datos; es responsabilidad del programador usar los operadores apropiados para leer (fetch) y para almacenar (store) los valores o para realizar otras operaciones con los datos.
Programación
Las palabras escritas en Forth son compiladas en una forma ejecutable. Las implementaciones clásicas de «enhebrado indirecto» (indirect threaded) compilan listas de las direcciones de las palabras a ser ejecutadas; muchos sistemas modernos generan código de máquina real (incluyendo llamadas a ciertas palabras y códigos externos para otros ampliados en el mismo lugar). Algunos sistemas tienen compiladores de optimización. Hablando en términos generales, un programa Forth es guardado como la imagen de memoria del programa compilado con un solo comando (ej., RUN) que es ejecutado cuando es cargada la versión compilada.
Durante el desarrollo, el programador usa al interpretador para ejecutar y probar cada pequeña pieza a medida que es desarrollada. Por lo tanto, la mayoría de los programadores Forth defienden un diseño de arriba hacia abajo (top-down) flojo, y el desarrollo de abajo hacia arriba (bottom-up) con la prueba y la integración continuos.[24]
El diseño de arriba hacia abajo es generalmente una separación del programa en «vocabularios» que entonces son usados como conjuntos de herramientas de alto nivel para escribir el programa final. Un programa Forth bien diseñado se lee como el lenguaje natural, e implementa no solo una sola simple solución, sino también un conjunto de herramientas para atacar problemas relacionados.[25]
Implementaciones
Puesto que la máquina virtual del Forth es simple de implementar y no tiene ninguna referencia estándar de implementación, hay una plétora de implementaciones del lenguaje. Además de soportar las variedades estándar de los sistemas de computadora de escritorio (POSIX, Microsoft Windows, Mac OS X), muchos de estos sistemas Forth también apuntan a una variedad de sistemas embebidos. Listados aquí están algunos de los sistemas más prominentes que se conforman al estándar ANS Forth 1994.
↑ abcC. H. Moore; E. D. Rather; D. R. Colburn (abril de 1993). «The Evolution of Forth». ACM SIGPLAN Notices, Volume 28, No. 3. March, 1993. ACM SIGPLAN History of Programming Languages Conference.
↑Brodie, Leo (1987). «Under The Hood». Starting Forth(paperback|formato= requiere |url= (ayuda)) (2nd edición). Prentice-Hall. p. 241. ISBN0-13-843079-9. «To summarize, there are three kinds of variables: System variables contain values used by the entire Forth system. User variables contain values that are unique for each task, even though the definitions can be used by all tasks in the system. Regular variables can be accessible either system-wide or within a single task only, depending upon whether they are defined within OPERATOR or within a private task.»
↑The classic washing machine example describes the process of creating a vocabulary to naturally represent the problem domain in a readable way.
Bibliografía
Brodie, Leo (2007). Marcel Hendrix, ed. Starting Forth(Online book). Marlin Ouverson (Web edition edición). FORTH, Inc. Consultado el 29 de septiembre de 2007.
Brodie, Leo (2004). Bernd Paysan, ed. Thinking Forth(PDF Online book). ISBN0-9764587-0-5. Archivado desde el original el 16 de diciembre de 2005. Consultado el 15 de septiembre de 2008.
Conklin, Edward K.; Elizabeth D. Rather et al. (8 de septiembre de 2007). Forth Programmer's Handbook(paperback) (3rd edición). BookSurge Publishing. p. 274. ISBN1-4196-7549-4.La referencia utiliza el parámetro obsoleto |coautores= (ayuda)
Pelc, Stephen F. Programming Forth(spiral bound). MicroProcessor Engineering Ltd. p. 188. Archivado desde el original el 11 de enero de 2008. Consultado el 17 de agosto de 2009.