Lenguaje de programación de sistemas - Systems Programming Language
| Paradigmas | procedimental , imperativo , estructurado |
|---|---|
| Familia | ALGOL |
| Apareció por primera vez | 1972 |
| Influenciado por | |
| ALGOL 60 , ESPOL | |
| Influenciado | |
| ZSPL, Micro-SPL, ¡Acción! | |
El lenguaje de programación de sistemas , a menudo abreviado a SPL pero a veces conocido como SPL / 3000 , era un lenguaje de programación orientado a procedimientos escrito por Hewlett-Packard para la línea de minicomputadoras HP 3000 y presentado por primera vez en 1972. SPL se usó para escribir el sistema operativo principal de la HP 3000 Sistema , Ejecutivo de Programación Múltiple (MPE). Los lenguajes similares en otras plataformas se denominaron genéricamente lenguajes de programación del sistema , lo que resulta confuso.
Originalmente conocido como Alpha Systems Programming Language , llamado así por el proyecto de desarrollo que produjo la serie 3000, SPL fue diseñado para aprovechar el diseño de procesador basado en pila de Alpha . Se basa en ESPOL , un lenguaje derivado de ALGOL similar utilizado por los sistemas de mainframe Burroughs B5000 , que también influyó en varios lenguajes de la década de 1960 como PL360 y JOVIAL .
A mediados de la década de 1970, el éxito de los sistemas HP produjo una serie de ramificaciones de SPL. Los ejemplos incluyen ZSPL para el procesador Zilog Z80 y Micro-SPL para Xerox Alto . ¡La acción inspirada más tarde ! para la familia Atari de 8 bits , que tuvo bastante éxito. Este último siguió más de cerca la sintaxis de Pascal , perdiendo algunas de las idiosincrasias de SPL.
SPL fue ampliamente utilizado durante la vida útil de las versiones originales basadas en circuitos integrados de la plataforma HP 3000. En la década de 1980, HP 3000 y MPE se volvieron a implementar en un emulador que se ejecutaba en las plataformas HP 9000 basadas en PA-RISC . HP promovió Pascal como el lenguaje de sistema preferido en PA-RISC y no proporcionó un compilador SPL. Esto provocó problemas de mantenimiento de código , y se introdujeron compiladores SPL de terceros para satisfacer esta necesidad.
Historia
Hewlett-Packard presentó sus primeras miniordenadores , la serie HP 2100 , en 1967. Las máquinas habían sido diseñadas originalmente por un equipo externo que trabajaba para Union Carbide y estaban destinadas principalmente a usos industriales de control integrado, no al mercado más amplio de procesamiento de datos. HP vio esto como un ajuste natural con su negocio de instrumentación existente e inicialmente lo presentó a esos usuarios. A pesar de esto, HP descubrió que la relación precio / rendimiento de la máquina los hacía cada vez más exitosos en el mercado empresarial.
Durante este período, el concepto de tiempo compartido se estaba volviendo popular, especialmente a medida que disminuían los costos de la memoria central y los sistemas comenzaron a distribuirse con más memoria. En 1968, HP introdujo un sistema integrado que utilizaba dos máquinas de la serie 2100 que ejecutaban HP Time-Shared BASIC , que proporcionaba un sistema operativo completo , así como el lenguaje de programación BASIC . Estos sistemas de dos máquinas, conocidos colectivamente como HP 2000, fueron un éxito inmediato. HP BASIC fue muy influyente durante muchos años, y su sintaxis se puede ver en varios microordenadores BASIC, incluidos Palo Alto TinyBASIC , Integer BASIC , North Star BASIC , Atari BASIC y otros.
Los diseñadores de HP comenzaron a preguntarse: "Si podemos producir un sistema de tiempo compartido tan bueno usando una computadora chatarra como la 2116, piensen en lo que podríamos lograr si diseñáramos nuestra propia computadora". Con este fin, en 1968 la empresa comenzó a formar un equipo más grande para diseñar una nueva arquitectura de tamaño medio. Los nuevos miembros del equipo incluían a aquellos que habían trabajado en los sistemas mainframe de Burroughs e IBM , y los conceptos resultantes se parecían mucho al sistema Burroughs B5000 de gran éxito . El B5000 utilizó un procesador de máquina de pila que simplificó la implementación de la multiprogramación , y esta misma arquitectura también se seleccionó para el nuevo concepto de HP.
Se consideraron dos implementaciones, una máquina a escala de mainframe de 32 bits conocida como Omega y un diseño de 16 bits conocido como Alpha. Casi todo el esfuerzo estaba en el Omega, pero en junio de 1970, Omega fue cancelado. Esto llevó a un rediseño extenso de Alpha para diferenciarlo del 2100, y finalmente surgió con planes para un diseño de sistema operativo aún más agresivo. Omega tenía la intención de ejecutarse en modo por lotes y utilizar una computadora más pequeña, la "interfaz", para procesar las interacciones con el usuario. Este era el mismo concepto operativo que la serie 2000. Sin embargo, otro 2000 no sería suficiente para Alpha, y se tomó la decisión de tener un solo operativo para operación por lotes, interactiva e incluso en tiempo real .
Para que esto funcionara, necesitaba un diseño de bus de computadora avanzado con amplio acceso directo a memoria (DMA) y requería un sistema operativo (SO) avanzado para brindar respuestas rápidas a las acciones del usuario. El B5000 también fue único, para su época, en el sentido de que su sistema operativo y las utilidades principales se programaron en un lenguaje de alto nivel , ESPOL . ESPOL fue un derivado del lenguaje ALGOL sintonizado para trabajar en el B5000, un concepto que fue muy influyente en la década de 1960 y condujo a nuevos lenguajes como JOVIAL , PL / 360 y BCPL . El equipo de HP decidió que también usarían un lenguaje derivado de ALGOL para el trabajo de sus sistemas operativos. El lenguaje similar de HP se conoció inicialmente como el lenguaje de programación Alpha Systems.
Alpha tardó varios años en desarrollarse antes de emerger en 1972 como HP 3000. La máquina estuvo en el mercado solo unos meses antes de que quedara claro que simplemente no funcionaba bien, y HP se vio obligada a retirar todas las 3000 ya vendidas. Se reintrodujo a finales de 1973 y se solucionaron la mayoría de sus problemas. Una importante actualización de todo el sistema, la máquina CX y el MPE-C para funcionar en él, reformó su imagen y la 3000 pasó a ser otro gran éxito durante la segunda mitad de la década de 1970.
Este éxito hizo que SPL estuviera casi tan extendido como el BASIC de la serie 2000 y, al igual que ese lenguaje, SPL dio como resultado varias versiones para otras plataformas. Entre ellos se destacó Micro-SPL, una versión escrita para la estación de trabajo Xerox Alto . Esta máquina había utilizado originalmente BCPL como su idioma principal, pero la insatisfacción con su desempeño llevó a Henry Baker a diseñar un lenguaje no recursivo que implementó con Clinton Parker en 1979. Clinton luego modificaría aún más Micro-SPL para producir Action! para la familia Atari de 8 bits en 1983.
HP volvió a implementar el sistema HP 3000 en el chipset PA-RISC, ejecutando una nueva versión del sistema operativo conocida como MPE / iX. MPE / iX tenía dos modos, en "modo nativo" ejecutaba aplicaciones que habían sido recompiladas para el PA-RISC usando compiladores Pascal más nuevos, mientras que en "modo compatible" podía ejecutar todo el software existente mediante emulación. HP no proporcionó un compilador de modo nativo para MPE / iX, por lo que no fue un proceso fácil trasladar el software existente a la nueva plataforma. Para satisfacer la necesidad, Allegro Consultants escribió un lenguaje compatible con SPL llamado "SPLash!" que podría compilarse en el código HP 3000 original para ejecutarse dentro del emulador o en modo nativo. Esto ofreció una vía de transferencia para el software SPL existente.
Idioma
Sintaxis básica
SPL generalmente sigue las convenciones de sintaxis de ALGOL 60 y será familiar para cualquiera con experiencia en ALGOL o sus descendientes, como Pascal y Modula-2 . Al igual que esos lenguajes, las declaraciones de programa pueden abarcar varias líneas físicas y terminar con un punto y coma. Los comentarios se indican con la COMMENT palabra clave o rodeando el texto del comentario entre << y >>.
Las declaraciones se agrupan en bloques utilizando BEGIN y END, aunque, como en Pascal, el END de un programa debe ir seguido de un punto. El programa en su conjunto está rodeado por BEGIN y END., Similar a Pascal, pero sin una palabra clave PROGRAM o una declaración similar en la parte superior. La razón de esto es que SPL permite que cualquier bloque de código se use como un programa por sí solo o se compile en otro programa para que actúe como una biblioteca. La creación de código como un programa o subprograma no era parte del lenguaje en sí, sino que se manejaba colocando la $CONTROL SUBPROGRAM directiva del compilador en la parte superior del archivo.
El idioma utilizó la palabra clave INTRINSIC para permitir que se llame directamente a un código externo dándole un nombre local. Por ejemplo, una biblioteca de lenguaje de máquina que exponga una función para ejecutar el timbre de la consola podría importarse a un programa SPL como INTRINSIC BELL y luego el timbre podría operarse usando la palabra clave BELL como si fuera un comando nativo.
En contraste con Pascal, donde PROCEDURE y FUNCTION eran conceptos separados, SPL usa un enfoque más parecido a C donde cualquiera PROCEDURE puede tener un prefijo con un tipo para convertirlo en una función. De acuerdo con la sintaxis de otros lenguajes similares a ALGOL, los tipos de parámetros se enumeran después del nombre, no como parte de él. Por ejemplo:
INTEGER PROCEDURE FACT(N); VALUE N; INTEGER N;
Declara una función FACT que toma un valor N que es un número entero. El VALUE indica que esta variable también es el valor de retorno del procedimiento.
Aunque estaban mal vistos, ALGOL y Pascal permitieron que el código se etiquetara con un nombre inicial que terminara con dos puntos, que luego podría usarse para el destino de los bucles y las GO TO declaraciones. Una pequeña diferencia es que SPL requería que los nombres de las etiquetas se declararan en la sección de variables usando la LABEL palabra clave.
SPL agregó a este concepto con la ENTRY declaración que permitió que estas etiquetas se definieran más a fondo como "puntos de entrada" a los que se podía acceder desde la línea de comandos. Las etiquetas nombradas en las declaraciones de entrada se expusieron al sistema operativo y se podían llamar desde el comando RUN. Por ejemplo, se podría escribir un programa que contenga funciones de cadena para convertir a mayúsculas o minúsculas, y luego proporcionar puntos de ENTRADA para estos dos. Esto se podría llamar desde la línea de comandos como RUN $STRINGS,TOUPPER .
Tipos de datos
Donde SPL difiere más notablemente de ALGOL es que sus tipos de datos son muy específicos de la máquina, basados en el formato de palabra big endian de 16 bits de 3000 .
El INTEGER tipo es un tipo con signo de 16 bits, con 15 bits de valor y el bit menos significativo como signo. DOUBLE es un entero de 32 bits, no un tipo de punto flotante. REAL es un valor de coma flotante de 32 bits con 22 bits para la mantisa y 9 para el exponente, mientras que LONG es un valor de coma flotante de 64 bits con 54 bits de mantisa y exponente de 9 bits.
BYTE se utiliza para el procesamiento de caracteres, que consta de una palabra de máquina de 16 bits que contiene dos caracteres de 8 bits. LOGICAL es un tipo booleano que almacena un solo bit en el bit más significativo . No existe un equivalente de un PACKED modificador como el que se encuentra en Pascal, por lo que LOGICAL es un desperdicio de memoria.
Al igual que C, los datos tienen un tipo débil , las ubicaciones de la memoria y el almacenamiento de variables son conceptos entremezclados y se puede acceder a los valores directamente a través de sus ubicaciones. Por ejemplo, el código:
INTEGER A,B,C LOGICAL D=A+2
define tres variables enteras de 16 bits, A, B y C, y luego una LÓGICA, también un valor de 16 bits. El = , como Pascal, significa "es equivalente a", no "obtiene el valor de", que se usa := en lenguajes similares a Algol. Entonces, la segunda línea dice "declarar una variable D que está en la misma ubicación de memoria que A + 2", que en este caso también es la ubicación de la variable C. Esto permite que el mismo valor se lea como un número entero a través de C o una lógica a través de D.
Esta sintaxis puede parecer extraña para los lectores modernos donde la memoria es generalmente una caja negra , pero tiene varios usos importantes en la programación de sistemas donde ubicaciones de memoria particulares contienen valores del hardware subyacente. En particular, permite definir una variable que apunta al frente de una tabla de valores y luego declarar variables adicionales que apuntan a valores individuales dentro de la tabla. Si la ubicación de la tabla cambia, solo debe cambiar un valor único, la dirección inicial y todas las variables individuales seguirán automáticamente en sus correspondientes compensaciones relativas.
Los punteros se declararon agregando el POINTER modificador a cualquier declaración de variable, y la ubicación de memoria de una variable desreferenciada con @ . Por lo tanto, INTEGER POINTER P:=@A declara un puntero cuyo valor contiene la dirección de la variable A, no el valor de A. @ puede usarse en cualquier lado de la asignación; @P:=A pone el valor de A en P, lo que probablemente resulte en un puntero colgante , @P:=@A hace que P apunte a A, mientras que P:=A pone el valor de A en la ubicación apuntada actualmente por P.
De manera similar, SPL incluye soporte de matriz de tipo C en el que la variable de índice es un desplazamiento de número de palabras desde la ubicación de memoria establecida para la variable inicial. A diferencia de C, SPL solo proporcionó matrices unidimensionales y usó paréntesis en lugar de corchetes. También se podían declarar variables GLOBAL , en cuyo caso no se reservaba memoria local para ellas y se suponía que el almacenamiento estaba declarado en otra biblioteca. Esto refleja la extern palabra clave en C.
Los literales se pueden especificar con varios sufijos, y se supone que los que no tienen sufijo INTEGER . Por ejemplo, 1234 se interpretaría como un INTEGER , mientras que 1234D era un DOUBLE . E denota una REAL y L una LONG . Las constantes de cadena se delimitaron con comillas dobles y las comillas dobles dentro de una línea se escaparon con una segunda comilla doble.
Las declaraciones de variables podrían usar constantes para definir un valor inicial, como en INTEGER A:=10 . Tenga en cuenta el uso de assign-to en lugar de is-a. Además, SPL tenía una EQUATE palabra clave que permitía definir una cadena de texto como una variable y luego reemplazaba cualquier instancia de esa variable en el código con la cadena literal durante las compilaciones. Esto es similar a la const palabra clave en C.
Segmentación de la memoria
Como era común en la época, la HP 3000 usaba un modelo de memoria segmentada orientada a bytes en el que una dirección era una sola palabra de 16 bits, lo que permitía que el código tuviera acceso a hasta 65,536 bytes (o como lo llamaron, "medias palabras" ). Para permitir el acceso a grandes cantidades de memoria, se utilizó un sistema de memoria virtual . Cuando se accedió a la memoria, la dirección de 16 bits tenía como prefijo uno de los dos valores de segmento de 8 bits, uno para el código de programa (PB) y otro para los datos variables. El resultado fue una dirección de 24 bits. Por lo tanto, si bien cada programa tenía acceso a un total de 128 kB en cualquier momento, podía intercambiar los segmentos para acceder a un espacio de memoria completo de 16 MB.
SPL incluía una variedad de sistemas de soporte para permitir que los programas se segmentaran fácilmente y luego hacer esa segmentación relativamente invisible en el código. El mecanismo principal era utilizar la $CONTROL SEGMENT=asegmentname directiva del compilador que definía en qué segmento se debía colocar el siguiente código. El valor predeterminado era MAINLINESEG , pero el programador podía agregar cualquier número de segmentos adicionales con nombre para organizar el código en bloques.
Otras características
SPL incluía una función de "extracción de bits" que permitía manipular bits de forma simplificada . Se puede acceder a cualquier bit, o cadena de bits, en una palabra usando la .(x:y) sintaxis, donde xey eran las posiciones de bit inicial y final de 0 a 15. Por lo tanto, se A.(8:15) devuelve el byte inferior de la palabra almacenando A. Este formato podría usarse para dividir y fusionar bits según sea necesario. Además, se proporcionaron operaciones adicionales para turnos y rotaciones, y podrían aplicarse a cualquier variable con & , por ejemplo A:=A & LSR(3) .
Ejemplo
Este sencillo programa, de la versión de 1984 del manual de referencia, muestra la mayoría de las características del lenguaje SPL.
El programa en su conjunto se delimita entre BEGIN y END. . Comienza con la definición de una serie de variables globales, A, B y C, define un solo procedimiento y luego lo llama veinte veces. Tenga en cuenta que el procedimiento no tiene comienzan y terminan de su propia, ya que contiene una sola línea de código real, X:=X*(Y+Z); la INTEGER X,Y,Z parte que no se considera del propio código, que es lo que indica el tipo de los tres parámetros que se pasa en la línea anterior y se considera parte de esa línea.
BEGIN
INTEGER A:=0, B, C:=1;
PROCEDURE N(X,Y,Z);
INTEGER X,Y,Z;
X:=X*(Y+Z);
FOR B:=1 UNTIL 20 DO
N(A,B,C);
END.
Referencias
Citas
Bibliografía
- Edler, Christopher (noviembre de 1995). "El castillo más fuerte: el ascenso, caída y ascenso de la HP 3000" . El motor analítico . 3 (1). ISSN 1071-6351 . Archivado desde el original el 3 de febrero de 2002.
- Green, Bob (2004). HP3000 Evolution . Robelle .
- Manual de referencia del lenguaje de programación de sistemas (PDF) . Hewlett Packard. Febrero de 1984.