HyperTalk es un lenguaje de programación procedimental de alto nivel que ya no se fabrica, creado en 1987 por Dan Winkler y utilizado junto con el programa de hipermedia HyperCard de Apple Computer por Bill Atkinson . Debido a que el público objetivo principal de HyperTalk eran los programadores principiantes, los programadores de HyperTalk solían denominarse "autores" y el proceso de escritura de programas se conocía como " scripting ". Los scripts de HyperTalk se parecían al inglés escrito y utilizaban una estructura lógica similar a la del lenguaje de programación Pascal .
HyperTalk admitía las estructuras de control básicas de los lenguajes procedimentales : repetición for/while/until, if/then/else, así como llamadas a funciones y "manejadores" de mensajes (un manejador de funciones era una subrutina y un manejador de mensajes un procedimiento). Normalmente, el programador no necesitaba especificar los tipos de datos ; la conversión se producía de forma transparente en segundo plano entre cadenas y números. No había clases ni estructuras de datos en el sentido tradicional; en su lugar había literales de cadena especiales o "listas" de "elementos" delimitados por comas (en versiones posteriores, la propiedad "itemDelimiter" permitía elegir un carácter arbitrario). La ejecución del código normalmente comenzaba como respuesta a un evento, como un clic del ratón en un widget de la interfaz de usuario.
A finales de los años 1980, Apple consideró [1] utilizar el lenguaje de programación HyperTalk de HyperCard como lenguaje estándar en toda la empresa y dentro de su sistema operativo clásico Mac OS , así como para la comunicación entre procesos entre productos Apple y no Apple. La empresa no se opuso al desarrollo de imitaciones como SuperCard , pero creó el Comité de estándares HyperTalk para evitar la incompatibilidad entre variantes del lenguaje. [1] El lenguaje , que no distinguía entre mayúsculas y minúsculas , fue inicialmente interpretado , pero ganó la compilación justo a tiempo con HyperCard 2.0. [2]
Para la mayoría de las operaciones básicas, incluidos los cálculos matemáticos, HyperTalk prefirió el ordenamiento de predicados en lenguaje natural en lugar del ordenamiento utilizado en la notación matemática. Por ejemplo, en put
el comando de asignación de HyperTalk, la variable se colocó al final de la declaración:
Ponga 5 * 4 en el resultado
Mientras que en el lenguaje de programación BASIC más tradicional (y la mayoría de los otros), lo mismo se lograría escribiendo:
elResultado = 5 * 4
El código de HyperTalk tiene el efecto secundario de crear la variable theResult sobre la marcha. Los scripts podían asignar cualquier tipo o valor a una variable usando el put
comando, lo que hacía que HyperTalk fuera muy poco tipado . Las conversiones entre tipos de variables eran invisibles y automáticas: la cadena "3" podía multiplicarse por el número 5 para producir el número 15, o el número 5 concatenado con la cadena "3" para producir la cadena "35". HyperTalk no se quejaba a menos que los tipos no pudieran convertirse automáticamente.
El control de flujo y la lógica del lenguaje eran en general similares a los de otros lenguajes comunes, ya que utilizaban una if ... then ... else ... end if
estructura para condicionales y bucles de soporte basados en una repeat ... end repeat
sintaxis flexible. Los comentarios iban precedidos por dos signos menos: -- this is a comment
.
El concepto principal de interfaz de usuario de HyperCard era la tarjeta , un sistema de visualización que emulaba una tarjeta de índice . Las tarjetas se usaban normalmente para almacenar información, de forma similar a un registro en una base de datos de archivo plano convencional . El diseño gráfico de la tarjeta se creaba utilizando el ratón colocando varios elementos en la tarjeta, como campos de texto y botones. Una "tarjeta" de diseño maestra conocida como fondo se mostraba detrás de las áreas transparentes de cada tarjeta. Los objetos colocados en el fondo, como campos y botones, se compartirían como un diseño común entre varias tarjetas, pero con contenido específico de la tarjeta. La colección de tarjetas, fondos y los datos asociados almacenados en ellas se almacenaban en un solo archivo conocido como la pila (de tarjetas). En conjunto, todos estos objetos que contienen datos se denominan contenedores .
Las funciones de HyperTalk, o scripts , normalmente se almacenaban dentro de la script
propiedad disponible en muchos de los contenedores de la pila. Los scripts podían acceder a las propiedades de un contenedor, correspondientes a las variables de instancia , utilizando las instrucciones get
y set
. La propiedad script contenía texto sin formato y no tenía propiedades especiales; los scripts se podían colocar y ejecutar desde cualquier contenedor de texto, incluidas las variables de cadena [a] o importar desde otras pilas utilizando el start using
comando. Un script incluso podía ser texto proporcionado por el usuario escrito en un campo de texto en pantalla. Se podía ejecutar texto arbitrario utilizando el do
comando, de manera similar a SQL dinámico. [3]
Un concepto clave en HyperTalk era la forma en que se hacía referencia a los contenedores a través de un sistema de navegación basado en la jerarquía visual de la pila. A cada contenedor de la pila se le asignaba un número de identificación único cuando se creaba y también se le podía asignar un nombre opcional. Los scripts podían hacer referencia a objetos utilizando cualquiera de estos identificadores, junto con un tipo de objeto especificado mediante el of
operador. Este operador utilizaba una sintaxis de lenguaje natural que permitía obtener un código autodocumentado y de fácil lectura . Por ejemplo, un script almacenado en un botón de una tarjeta podría querer tomar el texto proporcionado por el usuario recopilado mediante un campo de texto y almacenarlo en una variable llamada theValue :
Coloque el valor del campo de tarjeta "typehere" en el campo Value
El intérprete podía inferir diversos aspectos contextuales de las declaraciones. En la declaración anterior, por ejemplo, dado que el script se ejecutaba en el contexto de un botón en una tarjeta específica, se entendía que la tarjeta identificadora se refería a la tarjeta con la que estaba interactuando el usuario, aunque el botón en sí normalmente estaría en segundo plano. Además, se suponía que " el valor " (el texto enviado por el usuario) era la propiedad principal y el objetivo de las operaciones si no se especificaba lo contrario. Del mismo modo, se suponía que " el campo de la tarjeta " era el objetivo del comando, en lugar del campo de fondo, de modo que también se podía omitir esa información. Incluso los tipos de contenedor tenían formas cortas que los programadores podían usar para ahorrar escritura. Por lo tanto, el código anterior es equivalente a la forma corta:
Coloque el campo "typehere" en el valor
A los objetos dentro de un contexto determinado (la tarjeta o el fondo, por ejemplo) también se les asignaba un número de tiempo de ejecución basado en su orden z en la pantalla. Para facilitar el uso de su posición para la navegación, HyperTalk también incluía una variedad de sistemas de referencia ordinales y cardinales para simplificar aún más la sintaxis. Suponiendo que el campo "typehere" es el único campo en la tarjeta, el código anterior también podría escribirse:
Coloque el primer campo de tarjeta en el Valor
o:
Coloque el campo de tarjeta 1 en el Valor
La elección del estilo de direccionamiento se dejó al programador; a menudo se usaban estilos diferentes en diferentes declaraciones dependiendo del estilo del código circundante para hacer el código más legible.
HyperTalk incluía el me
contenedor, que actuaba de la misma manera que el self
calificador que se encuentra en la mayoría de los lenguajes orientados a objetos , lo que permitía un acceso simple al objeto contenedor actual. Menos común era la it
variable, que contenía el valor de la última operación para ciertos operadores integrados. Por ejemplo:
Pregunta "¿Cuál es el valor?" y colócalo en el campo de la tarjeta "mostrar"
En este ejemplo, se utiliza el ask
comando para mostrar un cuadro de diálogo y capturar el texto escrito en un campo de texto adjunto; cuando se completa el diálogo al presionar Returno hacer clic en , el valor se asigna a la pseudovariable. Luego, la segunda línea copia ese valor en un campo de tarjeta mediante el operador de asignación.OKit
put
Los contenedores de un tipo determinado también estaban disponibles como colecciones con una versión pluralizada de ese tipo de contenedor como nombre: la colección de los campos de una tarjeta era card fields
. Estas colecciones eran, en sí mismas, contenedores con sus propias propiedades. La clave entre ellas era la number
propiedad que se usaba ampliamente durante las iteraciones y tareas similares. Por ejemplo, si uno quería ocultar todos los campos de una tarjeta, esto se podía lograr con este código:
repetir con i = 1 al número de campos de la tarjeta ocultar campo i fin repetir
Este código expone otra característica común de HyperTalk: que una propiedad puede tener varios nombres y operadores. En este caso, el hide
comando y el , asociado show
, actúan estableciendo el valor de la visible
propiedad del contenedor. Por lo tanto, hide field i
es exactamente equivalente a . Un ejemplo similar fue el comando que detuvo la actualización visual, que era una forma abreviada de , donde es una propiedad de HyperCard en sí misma, también un contenedor. Se encontraron muchos ejemplos de este tipo de sintaxis en HyperTalk, con el fin de simplificar la sintaxis y mejorar la legibilidad del código común.set the visible of field i to false
lock screen
set the lockscreen to true
lockscreen
En HyperCard 2.2 y versiones posteriores, la colección de colecciones también estaba disponible como contenedor parts
. Esto permitía que un script abordara todos los objetos de un contenedor con un único iterador.
Una característica notable del modelo de contenedores de HyperTalk era su manejo de texto. Cada colección de texto, ya sea una cadena literal en un programa o texto escrito en un campo de texto, se consideraba en sí misma un contenedor con múltiples colecciones de contenedores dentro de ella. Esto permitía que los scripts analizaran el texto utilizando los mismos comandos de navegación que cualquier otro contenedor. Por ejemplo, al analizar un archivo de datos delimitado por espacios, uno podría querer extraer la tercera columna, de esta manera:
Coloque la tercera palabra de FilesText en la columna Tres
Esta sintaxis permitía al script "recorrer" el texto para encontrar datos específicos, como en este ejemplo:
Coloque el primer carácter de la tercera palabra de la línea 5 del campo de tarjeta "sometext" en el Char
Este proceso de tratar el texto como un contenedor se conocía como "fragmentación" y las funciones como "expresiones fragmentadas". Estos mismos tipos de expresiones se utilizaban para gestionar la manipulación de archivos, junto con un conjunto de funciones de gestión de archivos. El siguiente código abre un archivo conocido, lee desde él, extrae datos y luego cierra el archivo:
en mouseDown responder archivo "Seleccione un archivo de texto para abrir". si está vacío , salga de mouseDown póngalo en filePath si hay un archivo filePath , abra el archivo filePath lea desde el archivo filePath hasta regresar póngalo en el campo cd "algún campo" cierre el archivo filePath establezca el estilo de texto del carácter 1 al 10 del campo de tarjeta "algún campo" en negrita fin si finaliza mouseDown
HyperTalk también incluye funciones para dividir cadenas en fragmentos mediante una operación de búsqueda de subcadenas con el in
operador . El siguiente código busca todos los ejemplos de un patrón determinado utilizando in
como parte del repeat
bucle, mientras que offset
busca la ubicación de ese patrón dentro de la cadena:
función replaceStr patrón , newStr , inStr repetir mientras patrón esté en inStr poner desplazamiento ( patrón , inStr ) en pos poner newStr en carácter pos a ( pos + la longitud de patrón ) - 1 de inStr fin repetir devolver inStr fin replaceStr
HyperTalk utilizó el mismo sistema de fragmentación para producir estructuras como matrices o listas. Dicha estructura se crearía colocando varios elementos de datos en una variable, separados por comas. Se podrían importar varios tipos de datos en un script de HyperTalk utilizando cadenas que se analizarían según fuera necesario. Por ejemplo, la posición de los objetos en la pantalla se definía mediante un par de números que representaban las coordenadas X e Y en relación con la esquina superior izquierda. El siguiente código crea una variable llamada pos que contiene un par de coordenadas y luego la manipula para reposicionar todos los botones de una tarjeta en diagonal desde la parte superior izquierda hasta la inferior derecha:
al colocar mouseUp, poner "100,100" en pos , repetir con x = 1 al número de botones de tarjeta , establecer la ubicación del botón de tarjeta x en pos, agregar 15 al elemento 1 de pos , finalizar repetición, finalizar mouseUp
La item
expresión de fragmentación se basaba originalmente en un delimitador de coma , pero versiones posteriores de HyperCard lo cambiaron al valor de itemDelimiter
, ofreciendo la capacidad de analizar listas y estructuras arbitrarias.
HyperTalk utilizó un concepto orientado a objetos para llamar a los scripts, en el que los objetos de la pila enviaban "eventos" como mensajes que serían procesados por controladores que declaraban su interés en recibir los eventos utilizando la on
sintaxis. Por ejemplo, la mayoría de los contenedores de GUI enviarían el mouseDown
mensaje cuando se hiciera clic en el botón del mouse y luego un mouseUp
mensaje cuando se soltara mientras aún se estaba sobre ese contenedor, y un script podría capturar estos eventos de la siguiente manera:
en mouseUp - coloque código adicional aquí fin mouseUp
Los mensajes de los eventos se enviaban primero al script del objeto que creaba el evento; por ejemplo, si el usuario hacía clic en un botón, el mouseUp
mensaje se enviaba primero a ese botón. Si el objeto de script del botón no tenía un mouseUp
controlador (o no tenía script alguno), se enviaba a la tarjeta, al fondo, a la pila, a cualquier pila cuyos scripts se hubieran importado explícitamente mediante el start using
comando, a la "pila de inicio" (una pila de HyperCard siempre abierta seleccionada por el usuario) y, por último, a la propia aplicación HyperCard.
Para muchos eventos simples, como hacer clic con el mouse sobre botones, el script se colocaría directamente dentro del objeto en cuestión, el botón en sí. Por ejemplo, se podría usar el código de ejemplo anterior dentro de un controlador de botones de esta manera:
al poner el ratón arriba repetir con i = 1 hasta el número de campos de la tarjeta ocultar campo i fin de repetición fin de ratón arriba
En el caso en que el código se llamara desde varias ubicaciones o se usara como controlador global para un evento, el script podría determinar el remitente original del evento mediante la target
función. Del mismo modo, los scripts podrían enviar eventos a otros contenedores mediante el send
comando y luego usar el código de navegación para hacer referencia al contenedor que contiene el código de ese controlador:
Envía "mouseUp" al botón de la tarjeta "OK" de la tarjeta "Veracidad"
La combinación del procesamiento de cadenas de HyperTalk con el do
comando permitió la construcción de intérpretes interactivos colocando un campo de texto en una tarjeta y luego colocando este código en el script del campo:
al presionar el mouseUp seleccionar clickLine poner la palabra 2 de clickLine en linenum hacer la línea linenum del campo 1 del cd al presionar el mouseUp
clickLine
es una propiedad global que devuelve el nombre y el número de línea del último campo en el que se hizo clic, en un formato como . Este código primero selecciona todo el texto en la línea en la que se hizo clic, luego extrae el número de línea en una variable local y luego lo usa para ejecutar el texto como un script de HyperCard.line 10 of card field 4
do
El mouseDown
mensaje se enviaba a un botón cuando el usuario hacía clic en él y mouseUp
se enviaba cuando el usuario soltaba el ratón dentro de él para activar su acción. De manera similar, HyperCard enviaba idle
mensajes periódicos, mouseEnter
, mouseLeave
, ... y varios otros mensajes relacionados con la navegación entre diferentes tarjetas en una pila de HyperCard, así como con la entrada del usuario ( keyDown
, functionKey
, ...) y eventos del sistema. En lo que respecta a los programadores, no había bucles de eventos principales como en otros lenguajes de programación procedimental.
A diferencia de las plataformas generales de desarrollo rápido de aplicaciones , las pilas de HyperCard siempre parecían pilas: la barra de menú era de HyperCard y no del programador (de manera predeterminada, los scripts podían agregar, eliminar y modificar menús), la ventana única tenía un tamaño fijo (en las primeras versiones) y, en ciertos casos, los comandos que eran centrales para la operación eran parte de la aplicación en sí y no estaban disponibles directamente en HyperTalk.
Un buen ejemplo de esto fue la creación de nuevas tarjetas, que era parte de la aplicación, no directamente accesible desde el lenguaje HyperTalk. Una nueva tarjeta solo se podía crear utilizando el elemento de menú Nueva tarjeta, que se podía simular en código utilizando doMenu "New Card"
. Mientras que HyperTalk invocaba comandos de menú, los comandos de menú también invocaban controladores en HyperTalk. Para ejecutar código personalizado cuando se seleccionaba el elemento de menú Copiar, se colocaba un script en la pila utilizando el on doMenu itemName
controlador y luego se examinaba itemName
para ver si era "Copiar".
HyperTalk también proporcionó control de script sobre las herramientas de dibujo integradas, simplemente programando los cambios necesarios en las herramientas de pintura y simulando los movimientos del mouse usando los comandos y .drag from start to end
click at position
Una distinción única entre el lenguaje de programación HyperTalk de HyperCard y lenguajes aparentemente similares como AppleScript era que los scripts HyperTalk eran más indulgentes en cuanto a la entrada que aceptaban.
Además de la declaración implícita de variables mencionada anteriormente cuando se les asigna un valor, y la forma en que los valores se convierten implícitamente entre tipos (lo que le permite, por ejemplo, solicitar character 2 of 1234
), HyperCard también reconocería ciertas expresiones y extraería subvalores de ellas.
Por ejemplo:
coloca la línea seleccionada del campo de tarjeta "Listbox" en la selección - da 'línea 2 a 3 del campo de tarjeta "Listbox"' selecciona la línea 1 del campo de tarjeta "Listbox" selecciona la línea ( palabra 2 de la selección ) del campo de tarjeta "Listbox" selecciona ( la línea seleccionada del campo de tarjeta "Listbox" ) - los paréntesis se agregaron solo con fines ilustrativos
o
tocar el clavicémbalo do mi sol tocar el clavicémbalo " do sol" poner "do sol" en la melodía tocar el clavicémbalo la melodía
Si bien el resultado final se parecía a los scripters como la expansión de variables de un script de Bash antes del análisis, se trataba de una sintaxis de caso especial y no tenía los inconvenientes de que los datos se evaluaran como código. Por ejemplo, todos los siguientes son errores de sintaxis en la melodía, no llamadas de función:
tocar el clavicémbalo "ceg()" poner "ce() g" en la melodía tocar el clavicémbalo la melodía
Aunque el lenguaje HyperTalk languideció al igual que el propio HyperCard, su interés revivió a través de su protocolo de complemento, los llamados Comandos externos (XCMD) y Funciones externas (XFCN), que eran contenedores de código nativo adjuntos a pilas (como recursos específicos de Macintosh ) con un único punto de entrada y valor de retorno. Los XCMD y XFCN podían llamarse como manejadores de mensajes y funciones normales desde scripts de HyperTalk, y también podían enviar mensajes de vuelta a la aplicación HyperCard. Algunos autores de XCMD añadieron características avanzadas como soporte de color completo (ColorizeHC, HyperTint, AddColor), múltiples ventanas de propósito especial (Prompt, Tabloid, Textoid, Listoid, ShowDialog, MegaWindows), soporte de arrastrar y soltar y varias interfaces de hardware al lenguaje.
Varios lenguajes de programación han implementado un superconjunto de HyperTalk (conocido colectivamente como xTalk ): [4]
Estos clones y dialectos (comúnmente conocidos bajo el nombre de lenguajes xTalk) agregaron al lenguaje varias características que se esperan de un lenguaje de programación moderno, como manejo de excepciones, propiedades de objetos definidas por el usuario, temporizadores, subprocesos múltiples e incluso objetos definidos por el usuario.
También hay lenguajes cuya sintaxis y estructura muestran influencias de HyperTalk, como:
Muchos nombres de métodos popularizados por primera vez por HyperTalk se han incorporado a lenguajes posteriores, como el onmouseup
controlador de eventos en JavaScript. [6] Aunque Asymetrix ToolBook a menudo también se considera un clon de HyperCard, su lenguaje de programación aparentemente tiene poca semejanza con HyperTalk.