PL/I

Ajustar Compartir Imprimir Citar
Lenguaje de programación de computación necesario

PL/I (Programming Language One, pronunciado y a veces escrito PL/1) es un lenguaje de programación informático imperativo y procedimental desarrollado y publicado por IBM. Está diseñado para la programación científica, de ingeniería, comercial y de sistemas. Ha sido utilizado por organizaciones académicas, comerciales e industriales desde que se introdujo en la década de 1960 y todavía se usa.

Los dominios principales de PL/I son el procesamiento de datos, la computación numérica, la computación científica y la programación de sistemas. Admite recursividad, programación estructurada, manejo de estructuras de datos vinculados, punto fijo, punto flotante, complejo, manejo de cadenas de caracteres y manejo de cadenas de bits. La sintaxis del lenguaje es similar al inglés y adecuada para describir formatos de datos complejos con un amplio conjunto de funciones disponibles para verificarlos y manipularlos.

Historia temprana

En la década de 1950 y principios de la de 1960, los usuarios comerciales y científicos programaban para diferentes equipos informáticos utilizando diferentes lenguajes de programación. Los usuarios comerciales pasaban de Autocoders a través de COMTRAN a COBOL, mientras que los usuarios científicos programaban en Fortran, ALGOL, GEORGE y otros. IBM System/360 (anunciado en 1964 y entregado en 1966) fue diseñado como una arquitectura de máquina común para ambos grupos de usuarios, reemplazando todas las arquitecturas de IBM existentes. De manera similar, IBM quería un único lenguaje de programación para todos los usuarios. Esperaba que Fortran pudiera ampliarse para incluir las funciones que necesitan los programadores comerciales. En octubre de 1963 se formó un comité compuesto originalmente por tres empleados de IBM de Nueva York y tres miembros de SHARE, la IBM grupo de usuarios científicos, para proponer estas extensiones a Fortran. Dadas las limitaciones de Fortran, no pudieron hacer esto y se embarcaron en el diseño de un nuevo lenguaje de programación basado libremente en ALGOL denominado NPL. Este acrónimo entró en conflicto con el del Laboratorio Nacional de Física del Reino Unido y fue reemplazado brevemente por MPPL (Lenguaje de programación multipropósito) y, en 1965, por PL/I (con un número romano "I"). La primera definición apareció en abril de 1964.

IBM tomó NPL como punto de partida y completó el diseño a un nivel en el que se pudo escribir el primer compilador: la definición de NPL estaba incompleta en alcance y detalles. El control del lenguaje PL/I recayó inicialmente en el Centro de Programación de Nueva York y más tarde en el Laboratorio de IBM UK en Hursley. Los grupos de usuarios de SHARE y GUIDE participaron en la extensión del lenguaje y desempeñaron un papel en el proceso de IBM para controlar el lenguaje a través de sus Proyectos PL/I. La experiencia de definir un lenguaje tan grande mostró la necesidad de una definición formal de PL/I. En 1967 se estableció un proyecto en el Laboratorio de IBM de Viena para realizar una especificación inequívoca y completa. Esto condujo a su vez a uno de los primeros métodos formales de desarrollo a gran escala, VDM.

A Fred Brooks se le atribuye haber asegurado que PL/I tuviera el tipo de datos CHARACTER.

El idioma se especificó en detalle por primera vez en el manual "PL/I Language Specifications. C28-6571", escrito en Nueva York en 1965 y reemplazado por "PL/I Language Specifications. GY33-6003", escrito por Hursley en 1967. IBM continuó desarrollando PL/I a finales de los sesenta y principios de los setenta, y lo publicó en el manual GY33-6003. Estos manuales fueron utilizados por el grupo Multics y otros implementadores tempranos.

El primer compilador se entregó en 1966. El estándar para PL/I se aprobó en 1976.

Objetivos y principios

Los objetivos de PL/I evolucionaron durante el desarrollo temprano del lenguaje. Se requería competitividad con el manejo de registros y la redacción de informes de COBOL. El alcance de la utilidad del lenguaje creció para incluir la programación del sistema y la programación basada en eventos. Los objetivos adicionales para PL/I fueron:

Para lograr estos objetivos, PL/I tomó prestadas ideas de lenguajes contemporáneos mientras agregaba nuevas capacidades sustanciales y las moldeaba con una sintaxis clara, concisa y legible. Muchos principios y capacidades se combinaron para darle al lenguaje su carácter y fueron importantes para alcanzar los objetivos del lenguaje:

Resumen de idioma

El lenguaje está diseñado para ser todo para todos los programadores. El resumen se extrae del estándar ANSI PL/I y el estándar de subconjunto de propósito general ANSI PL/I.

Un programa PL/I consta de un conjunto de procedimientos, cada uno de los cuales está escrito como una secuencia de sentencias. La construcción %INCLUDE se usa para incluir texto de otras fuentes durante la traducción del programa. Todos los tipos de declaraciones se resumen aquí en grupos que brindan una descripción general del lenguaje (el Estándar usa esta organización).

Categoría Estado
Estructura PROCEDURE (o PROC)
ENTRY
BEGIN
DO
END
Declarativo DECLARE (o DCL)
DEFAULT (o DFT)
FORMAT
Flujo de control CALL
IF
SELECT
GO TO
RETURN
STOP
Declaración de null
Categoría Estado
Manejo interrumpido ON
SIGNAL
REVERT
Almacenamiento ALLOCATE (o ALLOC)
FREE
Declaración de asignación
Input/Output OPEN
CLOSE
Corriente de entrada y salida GET
PUT
Entrada/salida récord READ
WRITE
REWRITE
LOCATE
DELETE

(Características como la multitarea y el preprocesador PL/I no están en el estándar pero son compatibles con el compilador PL/IF y algunas otras implementaciones se analizan en la sección Evolución del lenguaje).

Se pueden declarar nombres para representar datos de los siguientes tipos, ya sea como valores únicos o como agregados en forma de matrices, con un límite inferior y un límite superior por dimensión, o estructuras (que comprenden estructura anidada, matriz y variables escalares):

  • Arithmetic (expandido abajo)
  • CHARACTER
  • PICTURE for Arithmetic data
  • PICTURE for Character data
  • AREA
  • BIT
  • ENTRY
  • FILE
  • FORMAT
  • LABEL
  • OFFSET
  • POINTER

El tipo aritmético comprende estos atributos:

  • a base (BINARY o DECIMAL), y
  • a escala (FIXED o FLOAT), y
  • un modo (REAL o COMPLEX), y
  • a PRECISION ()number of digits, y para números de puntos fijos, a scale factor)

La base, la escala, la precisión y el factor de escala del tipo Picture-for-arithmetic están codificados dentro de la especificación de imagen. El modo se especifica por separado, con la especificación de imagen aplicada tanto a la parte real como a la imaginaria.

Los valores se calculan mediante expresiones escritas mediante un conjunto específico de operaciones y funciones integradas, la mayoría de las cuales se pueden aplicar tanto a valores agregados como individuales, junto con procedimientos definidos por el usuario que, del mismo modo, pueden operar y devolver valores agregados. así como valores únicos. La declaración de asignación asigna valores a una o más variables.

No hay palabras reservadas en PL/I. Una instrucción termina con un punto y coma. La longitud máxima de una declaración está definida por la implementación. Un comentario puede aparecer en cualquier parte de un programa donde se permite un espacio y está precedido por los caracteres barra inclinada, asterisco y termina con los caracteres asterisco, barra inclinada (es decir, /* Esto es un comentario. */). Las declaraciones pueden tener un prefijo de etiqueta que introduce un nombre de entrada (declaraciones ENTRY y PROCEDURE) o un nombre de etiqueta, y un prefijo de condición que habilita o deshabilita una condición computacional, p. (NOSIZE)). Los nombres de entradas y etiquetas pueden ser identificadores únicos o identificadores seguidos de una lista de subíndices de constantes (como en L(12,2):A=0;).

Una secuencia de sentencias se convierte en un grupo cuando va precedida de una sentencia DO y seguida de una sentencia END. Los grupos pueden incluir grupos anidados y bloques de inicio. La sentencia IF especifica un grupo o una sola sentencia como la parte THEN y la parte ELSE (ver el programa de ejemplo). El grupo es la unidad de iteración. El bloque de inicio (BEGIN; stmt-list END;) puede contener declaraciones para nombres y procedimientos internos locales al bloque. Un procedimiento comienza con una sentencia PROCEDURE y termina sintácticamente con una sentencia END. El cuerpo de un procedimiento es una secuencia de bloques, grupos y declaraciones y contiene declaraciones para nombres y procedimientos locales al procedimiento o EXTERNAL al procedimiento.

Una unidad ON es una sola declaración o bloque de declaraciones escritas para ser ejecutadas cuando ocurre una o más de estas condiciones:

una condición computacional,

  • CONVERSION (CONV)
  • FIXEDOVERFLOW (FOFL)
  • OVERFLOW (OFL)
  • SIZE
  • STRINGRANGE (STRG)
  • STRINGSIZE (STRZ)
  • SUBSCRIPTRANGE (SUBRG)
  • UNDERFLOW (UFL)
  • ZERODIVIDE (ZDIV)

o una condición de Entrada/Salida,

  • ENDFILE(file)
  • ENDPAGE(file)
  • KEY(file)
  • NAME(file)
  • RECORD(file)
  • TRANSMIT(file)
  • UNDEFINEDFILE(file) (UNDF)

o una de las condiciones:

La declaración de un identificador puede contener uno o más de los siguientes atributos (pero deben ser consistentes entre sí):

Atributos de datos Atributos de entrada/salida Otros atributos
ALIGNEDDIRECTAUTOMATIC or AUTO
AREA[(area-size)]ENVIRONMENT(options) or ENV...BASED[(reference)]
BINARY [(precision)] or BIN...INPUTBUILTIN
BIT [(maximum-length)]KEYEDCONDITION or COND
CHARACTER[(maximum-length)] or CHAR...OUTPUTCONSTANT
COMPLEX [(precision)] or CPLX...PRINTCONTROLLED or CTL
DECIMAL [(precision)] or DEC...SEQUENTIAL or SEQLDEFINED[(reference)] or DEF...
(dimension-attribute)STREAMEXTERNAL or EXT
ENTRY[(parameter descriptor list]UPDATEGENERIC(criteria list)
FILERECORDINITIAL(value-list) or INIT...
FIXED [(precision)]INTERNAL or INT
FLOAT [(number of digits)]LIKE unsubscripted reference
FORMATLOCAL
LABELOPTIONS(options)
MEMBERPARAMETER or PARM
NONVARYING or NONVARPOSITION [(expression)] or POS...
OFFSET[(reference)]STATIC
PICTURE picture-specification or PIC...VARIABLE
POINTER or PTR
STRUCTURE
UNALIGNED or UNAL
VARYING or VAR

Los compiladores actuales de Micro Focus, y en particular el de IBM, implementan muchas extensiones sobre la versión estandarizada del lenguaje. Las extensiones de IBM se resumen en la subsección Implementación para el compilador más adelante. Aunque hay algunas extensiones comunes a estos compiladores, la falta de un estándar actual significa que la compatibilidad no está garantizada.

Estandarización

La estandarización del idioma comenzó en abril de 1966 en Europa con ECMA TC10. En 1969, ANSI estableció un "Comité de desarrollo de lenguaje compuesto", apodado "Kludge", más tarde rebautizado como X3J1 PL/I. La estandarización se convirtió en un esfuerzo conjunto de ECMA TC/10 y ANSI X3J1. IBM ofreció un subconjunto del documento GY33-6003 al esfuerzo conjunto y se convirtió en el documento base para la estandarización. Las características principales omitidas del documento base fueron la multitarea y los atributos para la optimización del programa (por ejemplo, NORMAL y ABNORMAL).

Ambos comités votaron las propuestas para cambiar el documento base. En caso de que los comités no estuvieran de acuerdo, los presidentes, inicialmente Michael Marcotty de General Motors y C.A.R. Hoare en representación de ICL tuvo que resolver el desacuerdo. Además de IBM, Honeywell, CDC, Data General, Digital Equipment Corporation, Prime Computer, Burroughs, RCA y Univac trabajaron en X3J1 junto con los principales usuarios Eastman Kodak, MITRE, Union Carbide, Bell Laboratories y varios representantes gubernamentales y universitarios. Se produjo un mayor desarrollo del lenguaje en los organismos de estándares, con mejoras continuas en la programación estructurada y la coherencia interna, y con la omisión de las características más oscuras o polémicas.

A medida que el desarrollo del lenguaje llegaba a su fin, X3J1/TC10 se dio cuenta de que había una serie de problemas con un documento escrito en inglés. La discusión de un solo elemento puede aparecer en varios lugares que pueden o no estar de acuerdo. Fue difícil determinar si hubo omisiones además de inconsistencias. En consecuencia, David Beech (IBM), Robert Freiburghouse (Honeywell), Milton Barber (CDC), M. Donald MacLaren (Argonne National Laboratory), Craig Franklin (Data General), Lois Frampton (Digital Equipment Corporation) y el editor, D.J. Andrews de IBM se comprometió a reescribir todo el documento, cada uno produciendo uno o más capítulos completos. El estándar se expresa como una definición formal utilizando una "PL/I Machine" para especificar la semántica. Fue el primer estándar de lenguaje de programación, y posiblemente el único, que se escribió como una definición semiformal.

Un "Subconjunto de propósito general PL/I" ("Subset-G") fue emitido por ANSI en 1981 y se publicó una revisión en 1987. El subconjunto de propósito general fue ampliamente adoptado como núcleo para las implementaciones PL/I.

Implementaciones

Compiladores IBM PL/IF F y D

PL/I fue implementado por primera vez por IBM, en sus Laboratorios Hursley en el Reino Unido, como parte del desarrollo de System/360. El primer compilador PL/I de producción fue el compilador PL/IF para el sistema operativo OS/360, construido por el equipo de John Nash en Hursley en el Reino Unido: el equipo de la biblioteca de tiempo de ejecución estaba dirigido por I.M. (Nobby) Clarke. El compilador PL/IF se escribió completamente en lenguaje ensamblador System/360. La versión 1 se envió en 1966. OS/360 es un entorno de memoria real y el compilador fue diseñado para sistemas con tan solo 64 kilobytes de almacenamiento real; F es 64 kB en la jerga de S/360. Para acomodar un compilador grande en los 44 kilobytes de memoria disponibles en una máquina de 64 kilobytes, el compilador consta de una fase de control y un gran número de fases del compilador (cerca de 100). Las fases se traen a la memoria desde el disco, una a la vez, para manejar características particulares del lenguaje y aspectos de la compilación. Cada fase hace un solo paso sobre el programa parcialmente compilado, generalmente guardado en la memoria.

Todavía se estaban diseñando aspectos del lenguaje a medida que se implementaba PL/IF, por lo que algunos se omitieron hasta versiones posteriores. PL/I RECORD I/O se envió con PL/IF Release 2. Las funciones de procesamiento de listas (variables basadas, punteros, áreas y compensaciones y E/S en modo LOCATE) se enviaron por primera vez en la versión 4. En un importante intento de acelerar el código PL/I para competir con el código objeto de Fortran, PL/IF Release 5 realiza una optimización sustancial del programa de DO-loops facilitada por la opción REORDER en los procedimientos.

Se lanzó una versión de PL/IF en el sistema operativo de tiempo compartido TSS/360 para System/360 Model 67, adaptado en IBM Mohansic Lab. El laboratorio de IBM La Gaude en Francia desarrolló "Programas de conversión de idiomas" para convertir programas Fortran, Cobol y Algol al nivel PL/IF de PL/I.

El compilador PL/I D, que utiliza 16 kilobytes de memoria, fue desarrollado por IBM Alemania para el sistema operativo de gama baja DOS/360. Implementa un subconjunto del lenguaje PL/I que requiere que todas las cadenas y matrices tengan extensiones fijas, lo que simplifica el entorno de tiempo de ejecución. Reflejando el sistema operativo subyacente, carece de asignación de almacenamiento dinámico y de la clase de almacenamiento controlado. Fue enviado dentro de un año de PL/I F.

Multics PL / I y derivadas

(feminine)

Varios grupos implementaron compiladores a principios de la década de 1960. El proyecto Multics del MIT, uno de los primeros en desarrollar un sistema operativo en un lenguaje de alto nivel, utilizó Early PL/I (EPL), un subconjunto de dialectos de PL/I, como lenguaje de implementación en 1964. EPL se desarrolló en Bell Labs y MIT por Douglas McIlroy, Robert Morris y otros. Inicialmente, se desarrolló utilizando el compilador-compilador TMG. El influyente compilador Multics PL/I fue la fuente de la tecnología de compilación utilizada por varios fabricantes y grupos de software. EPL era un lenguaje de programación de sistemas y un dialecto de PL/I que tenía algunas capacidades ausentes en el PL/I original.

El compilador Honeywell PL/I (para la Serie 60) es una implementación del estándar ANSI X3J1 completo.

IBM PL/I optimización y compiladores de pago

Los compiladores PL/I Optimizer y Checkout producidos en Hursley admiten un nivel común de lenguaje PL/I y tenían como objetivo reemplazar el compilador PL/IF. El compilador de pago es una reescritura de PL/IF en BSL, el lenguaje de implementación propietario similar a PL/I de IBM (posteriormente PL/S). Los objetivos de rendimiento establecidos para los compiladores se muestran en una presentación de IBM al BCS. Los compiladores tenían que producir resultados idénticos: el Compilador de Checkout se usa para depurar programas que luego se enviarían al Optimizador. Dado que los compiladores tenían diseños completamente diferentes y manejaban el lenguaje PL/I completo, este objetivo fue un desafío: se logró.

IBM introdujo nuevos atributos y sintaxis que incluyen BUILTIN, sentencias de casos (SELECT/WHEN/OTHERWISE), controles de bucle (ITERATE y LEAVE) y listas de argumentos nulos para desambiguar, por ejemplo, DATE().

El compilador de optimización PL/I reemplazó al compilador PL/IF y fue el compilador caballo de batalla de IBM desde la década de 1970 hasta la década de 1990. Al igual que PL/IF, es un compilador de paso múltiple con un punto de diseño de 44 kilobytes, pero es un diseño completamente nuevo. A diferencia del compilador F, tiene que realizar una evaluación del tiempo de compilación de expresiones constantes utilizando la biblioteca de tiempo de ejecución, lo que reduce la memoria máxima para una fase del compilador a 28 kilobytes. Un diseño de segunda vez, logró eliminar las molestias de PL/IF, como los diagnósticos en cascada. Fue escrito en S/360 Macro Assembler por un equipo dirigido por Tony Burbridge, la mayoría de los cuales había trabajado en PL/IF. Las macros se definieron para automatizar los servicios comunes del compilador y para proteger a los escritores del compilador de la tarea de administrar los bienes inmuebles. modo de almacenamiento, lo que permite que el compilador se mueva fácilmente a otros modelos de memoria. Se implementó la gama de técnicas de optimización de programas desarrolladas para el compilador IBM Fortran H contemporáneo: el Optimizer igualó las velocidades de ejecución de Fortran en manos de buenos programadores. Anunciado con IBM S/370 en 1970, se envió primero para el sistema operativo DOS/360 en agosto de 1971, y poco después para OS/360, y los primeros sistemas operativos de memoria virtual de IBM OS/VS1, MVS y VM/CMS. (Los desarrolladores no sabían que, mientras estaban calzando el código en secciones de 28 kb, IBM Poughkeepsie finalmente estaba listo para enviar soporte de memoria virtual en OS/360). Admitía los entornos de programación por lotes y, bajo TSO y CMS, podía ejecutarse de forma interactiva. Este compilador pasó por muchas versiones que cubren todos los sistemas operativos de mainframe, incluidos los sistemas operativos de las máquinas japonesas compatibles con enchufes (PCM).

El compilador ha sido reemplazado por "IBM PL/I para OS/2, AIX, Linux, z/OS" abajo.

El compilador de pago PL/I (coloquialmente "The Checker") anunciado en agosto de 1970 fue diseñado para acelerar y mejorar la depuración de programas PL/I. El equipo fue dirigido por Brian Marks. El diseño de tres pasos redujo el tiempo de compilación de un programa al 25% del tiempo que toma el Compilador F. Se puede ejecutar desde una terminal interactiva, convirtiendo los programas PL/I a un formato interno, "H-text". Este formato es interpretado por el compilador de Checkout en tiempo de ejecución, detectando prácticamente todos los tipos de errores. Los punteros se representan en 16 bytes, que contienen la dirección de destino y una descripción del elemento al que se hace referencia, lo que permite que "mal" Uso del puntero para ser diagnosticado. En un entorno conversacional, cuando se detecta un error, el control pasa al usuario, que puede inspeccionar cualquier variable, introducir declaraciones de depuración y editar el programa fuente. Con el tiempo, la capacidad de depuración de los entornos de programación de mainframe desarrolló la mayoría de las funciones que ofrece este compilador y fue retirado (¿en la década de 1990?)

DIC PL/I

Quizás la implementación de mayor éxito comercial aparte de la de IBM fue VAX PL/I de Digital Equipment Corporation, más tarde conocida como DEC PL/I. La implementación es "un superconjunto estricto del subconjunto de propósito general ANSI X3.4-1981 PL/I y proporciona la mayoría de las funciones del nuevo subconjunto de propósito general ANSI X3.74-1987 PL/I", y se lanzó por primera vez en 1988. Originalmente usaba un backend compilador llamado VAX Code Generator (VCG) creado por un equipo dirigido por Dave Cutler. El front-end fue diseñado por Robert Freiburghouse y fue portado a VAX/VMS desde Multics. Se ejecuta en VMS en VAX y Alpha, y en Tru64. Durante la década de 1990, Digital vendió el compilador a UniPrise Systems, quien luego lo vendió a una empresa llamada Kednos. Kednos comercializó el compilador como Kednos PL/I hasta octubre de 2016, cuando la empresa dejó de operar.

Enseñanza de compiladores de subconjuntos

A fines de la década de 1960 y principios de la de 1970, muchas universidades estadounidenses y canadienses establecieron servicios de tiempo compartido en el campus y necesitaban compiladores/intérpretes conversacionales para su uso en la enseñanza de ciencias, matemáticas, ingeniería e informática. Dartmouth estaba desarrollando BASIC, pero PL/I era una opción popular, ya que era conciso y fácil de enseñar. Como las ofertas de IBM no eran adecuadas, varias escuelas crearon sus propios subconjuntos de PL/I y su propio soporte interactivo. Los ejemplos son:

En la década de 1960 y principios de la de 1970, Allen-Babcock implementó el sistema de tiempo compartido de usuarios remotos de hardware compartido (RUSH) para un IBM System/360 Model 50 con microcódigo personalizado y, posteriormente, implementó el CPS, un sistema interactivo de tiempo compartido para OS/360 destinado a enseñar conceptos básicos de informática, ofrecía un subconjunto limitado del lenguaje PL/I además de BASIC y una función de entrada de trabajo remota.

PL/C, un dialecto para la enseñanza, un compilador desarrollado en la Universidad de Cornell, tenía la capacidad inusual de nunca dejar de compilar ningún programa mediante el uso de una amplia corrección automática de muchos errores de sintaxis y por convirtiendo cualquier error de sintaxis restante en declaraciones de salida. El lenguaje era casi todo PL/I implementado por IBM. PL/C fue un compilador muy rápido.

SL/1 (Idioma del estudiante/1, Idioma del estudiante/Uno o Idioma del subconjunto/1) era un subconjunto PL/I, inicialmente disponible a fines de la década de 1960, que se ejecutaba de forma interpretativa en IBM 1130; el uso instructivo era su punto fuerte.

PLAGO, creado en el Instituto Politécnico de Brooklyn, utilizó un subconjunto simplificado del lenguaje PL/I y se centró en buenos mensajes de error de diagnóstico y tiempos de compilación rápidos.

El Grupo de Investigación de Sistemas Informáticos de la Universidad de Toronto produjo los compiladores SP/k que soportaban una secuencia de subconjuntos de PL/I llamados SP/1, SP/2, SP/3..., SP/8 para la enseñanza de la programación. Los programas que se ejecutaron sin errores con los compiladores SP/k produjeron los mismos resultados con otros compiladores PL/I contemporáneos, como el compilador PL/IF de IBM, el compilador checkout de IBM o el PL/ de la Universidad de Cornell. compilador C.

Otros ejemplos son PL0 de P. Grouse en la Universidad de Nueva Gales del Sur, PLUM de Marvin Victor Zelkowitz en la Universidad de Maryland y PLUTO de la Universidad de Toronto.

IBM PL/I para OS/2, AIX, Linux, z/OS

En una importante renovación de PL/I, IBM Santa Teresa en California lanzó un compilador completamente nuevo en 1992. El envío inicial fue para OS/2 e incluía la mayoría de las funciones ANSI-G y muchas funciones nuevas de PL/I. Las versiones posteriores proporcionaron plataformas adicionales (MVS, VM, OS/390, AIX y Windows), pero a partir de 2021, las únicas plataformas admitidas son z/OS y AIX. IBM continuó agregando funciones para hacer que PL/I fuera completamente competitivo con otros lenguajes (particularmente C y C++) en áreas donde había sido superado. El "IBM Language Environment" correspondiente admite la interoperación de programas PL/I con sistemas de bases de datos y transacciones, y con programas escritos en C, C++ y COBOL, el compilador admite todos los tipos de datos necesarios para la intercomunicación con estos lenguajes.

Los principios de diseño de PL/I se mantuvieron y resistieron esta gran extensión, que comprende varios tipos de datos nuevos, nuevas declaraciones y opciones de declaración, nuevas condiciones de excepción y nuevas organizaciones de origen del programa. El lenguaje resultante es un superconjunto compatible del estándar PL/I y de los compiladores anteriores de IBM. Los principales temas agregados a PL/I fueron:

La última serie de compiladores PL/I para z/OS, denominada Enterprise PL/I para z/OS, aprovecha la generación de código para los últimos procesadores z/Architecture (z14, z13, zEC12, zBC12, z196, z114) a través de el uso del control parm ARCHLVL pasó durante la compilación, y fue el segundo lenguaje de alto nivel admitido por z/OS Language Environment para hacerlo (XL C/C++ es el primero y Enterprise COBOL v5 el último).

Tipos de datos

ORDINAL es un nuevo tipo de datos computacionales. Las facilidades ordinales son como las de Pascal, p.ej. DEFINIR color ORDINAL (rojo, amarillo, verde, azul, violeta); pero además, el nombre y los valores internos son accesibles a través de funciones integradas. Las funciones integradas brindan acceso al predecesor y al sucesor de un valor ordinal.

La declaración-DEFINE (ver más abajo) permite que se declaren TYPE adicionales compuestos por los atributos integrados de PL/I.

El tipo de datos del localizador HANDLE(estructura de datos) es similar al tipo de datos POINTER, pero está fuertemente tipado para vincularse solo a una estructura de datos en particular. El operador => se utiliza para seleccionar una estructura de datos mediante un identificador.

El atributo UNION (equivalente a CELL en las primeras especificaciones PL/I) permite que varias variables escalares, arreglos o estructuras compartan el mismo almacenamiento en una unidad que ocupa la cantidad de almacenamiento necesaria para la alternativa más grande.

Competitividad en PC y con C

Se agregaron estos atributos:

Se agregaron nuevas funciones de manejo de cadenas: para centrar texto, editar usando un formato de imagen y recortar espacios en blanco o caracteres seleccionados del encabezado o final del texto, VERIFYR a VERIFY desde la derecha. y las funciones SEARCH y TALLY.

Operadores de asignación compuesta a la C, p. Se agregaron +=, &=, -=, ||=. A+=1 es equivalente a A=A+1.

Se agregaron atributos y descriptores de parámetros adicionales para argumentos omitidos y listas de argumentos de longitud variable.

Legibilidad del programa: hacer explícitas las intenciones

El atributo VALUE declara un identificador como una constante (derivada de un valor literal específico o expresión restringida).

Los parámetros pueden tener los atributos BYADDR (pasar por dirección) o BYVALUE (pasar por valor).

Los atributos ASSIGNABLE y NONASSIGNABLE evitan asignaciones no deseadas.

DO FOREVER; evita la necesidad de la construcción artificial DO WHILE ('1'B);.

La sentencia-DEFINE introduce nombres especificados por el usuario (por ejemplo, INTEGER) para combinaciones de atributos integrados (por ejemplo, FIXED BINARY(31,0)). Por lo tanto, DEFINE ALIAS INTEGER FIXED BINARY(31.0) crea el nombre TYPE INTEGER como un alias para el conjunto de atributos integrados FIXED BINARY(31.0). DEFINE STRUCTURE se aplica a las estructuras y sus miembros; proporciona un nombre TYPE para un conjunto de atributos de estructura y declaraciones de miembros de subestructura correspondientes para usar en una declaración de estructura (una generalización del atributo LIKE).

Adiciones a la programación estructurada

Una instrucción LEAVE para salir de un bucle y ITERATE para continuar con la siguiente iteración de un bucle.

Opciones

UPTHRU y DOWNTHRU en grupos iterativos.

La construcción del paquete que consta de un conjunto de procedimientos y declaraciones para usar como una unidad. Las variables declaradas fuera de los procedimientos son locales para el paquete y pueden usar almacenamiento STATIC, BASED o CONTROLLED. Los nombres de los procedimientos utilizados en el paquete también son locales, pero se pueden convertir en externos mediante la opción EXPORTS de la instrucción-PACKAGE.

Manejo de interrupciones

La sentencia-RESIGNAL ejecutada en una unidad ON finaliza la ejecución de la unidad ON y genera la condición nuevamente en el procedimiento que llamó a la actual (pasando así el control a la unidad ON correspondiente). unidad para ese procedimiento).

La condición INVALIDOP maneja códigos de operación no válidos detectados por el procesador de la PC, así como operaciones aritméticas ilegales como la resta de dos valores infinitos.

La condición ANYCONDITION se proporciona para interceptar condiciones para las que no se ha proporcionado ninguna unidad ON específica en el procedimiento actual.

La condición STORAGE se genera cuando una instrucción ALLOCATE no puede obtener suficiente almacenamiento.

Otros compiladores de mainframe y miniordenadores

Varios proveedores produjeron compiladores para competir con IBM PL/IF o el compilador de optimización en mainframes y minicomputadoras en la década de 1970. En la década de 1980, el objetivo solía ser el subconjunto ANSI-G emergente.

  • En 1974 Burroughs Corporation anunció PL/I para los B6700 y B7700.
  • UNIVAC publicó un UNIVAC PL/I y en los años 70 también utilizó una variante del PL/I, PL/I PLUS, para la programación del sistema.
  • De 1978 Data General proporcionó PL/I en sus plataformas Eclipse y Eclipse MV que ejecutan los sistemas operativos AOS, AOS/VS " AOS/VS II. En el idioma se redactaron varios programas de utilidad del sistema operativo.
  • Paul Abrahams del Courant Institute of Mathematical Sciences de NYU escribió CIMS PL/I en 1972 en PL/I, arrancando por PL/I F. Sostenía "alrededor del 70%" de la compilación PL/I al CDC 6600
  • CDC entregó un compilador de subconjunto optimizador PL/I para serie Cyber 70, 170 y 6000.
  • Fujitsu entregó un compilador PL/I equivalente al PL/I Optimizer.
  • Stratus Technologies PL/I es una aplicación ANSI G para el sistema operativo VOS.
  • IBM Series/1 PL/I es un subconjunto extendido de ANSI Programming Language PL/I (ANSI X3.53-1976) para el sistema de programación en tiempo real IBM Series/1.

Compiladores PL/I para Microsoft.NET

  • En 2011, Raincode diseñó un completo compilador legado para Microsoft. NET y. NET Plataformas básicas, llamada The Raincode PL/I compilador.

Compiladores PL/I para ordenadores personales y Unix

  • En la década de 1970 y 1980 Digital Research vendió un compilador PL/I para CP/M (PL/I-80), CP/M-86 (PL/I-86) y Computadoras Personales con DOS. Se basó en el subconjunto G de PL/I y fue escrito en PL/M.
  • Micro Focus implementó Open PL/I para sistemas Windows y UNIX/Linux, que adquirieron de Liant.
  • IBM entregó PL/I para OS/2 en 1994, y PL/I para AIX en 1995.
  • Iron Spring PL/I for OS/2 y más tarde Linux fue introducido en 2007.

Dialectos PL/I

Uso

Las implementaciones de PL/I se desarrollaron para mainframes a fines de la década de 1960, minicomputadoras en la década de 1970 y computadoras personales en las décadas de 1980 y 1990. Aunque su principal uso ha sido en mainframes, existen versiones PL/I para DOS, Microsoft Windows, OS/2, AIX, OpenVMS y Unix.

Ha sido ampliamente utilizado en el procesamiento de datos comerciales y para el uso del sistema para escribir sistemas operativos en ciertas plataformas. Se han construido sistemas muy complejos y potentes con PL/I:

PL/I no cumplió con sus partidarios' espera que desplace a Fortran y COBOL y se convierta en el actor principal de los mainframes. Siguió siendo un jugador minoritario pero significativo. No puede haber una explicación definitiva para esto, pero algunas tendencias en las décadas de 1970 y 1980 se opusieron a su éxito al reducir progresivamente el territorio en el que PL/I disfrutaba de una ventaja competitiva.

Primero, cambió la naturaleza del entorno de software de mainframe. Los subsistemas de aplicaciones para el procesamiento de bases de datos y transacciones (CICS e IMS y Oracle en System 370) y los generadores de aplicaciones se convirtieron en el foco de atención de los usuarios de mainframe. desarrollo de aplicaciones. Partes significativas del lenguaje se volvieron irrelevantes debido a la necesidad de usar las funciones nativas correspondientes de los subsistemas (como tareas y gran parte de la entrada/salida). Fortran no se usó en estas áreas de aplicación, limitando PL/I al territorio de COBOL; la mayoría de los usuarios se quedaron con COBOL. Pero a medida que la PC se convirtió en el entorno dominante para el desarrollo de programas, Fortran, COBOL y PL/I se convirtieron en lenguajes minoritarios superados por C++, Java y similares.

En segundo lugar, PL/I fue superado en el campo de la programación de sistemas. La comunidad de programación de sistemas de IBM no estaba lista para usar PL/I; en cambio, IBM desarrolló y adoptó un dialecto patentado de PL/I para la programación del sistema. – PL/S. Con el éxito de PL/S dentro de IBM y de C fuera de IBM, las fortalezas únicas de PL/I para la programación de sistemas se volvieron menos valiosas.

En tercer lugar, los entornos de desarrollo aumentaron las capacidades para el desarrollo de software interactivo que, una vez más, hizo que las fortalezas exclusivas de PL/I interactivas y de depuración fueran menos valiosas.

Cuarto, se agregaron a COBOL y Fortran funciones como programación estructurada, operaciones de cadenas de caracteres y orientación a objetos, lo que redujo aún más las ventajas relativas de PL/I.

En los mainframes, también estaban en juego cuestiones comerciales importantes. Los competidores de hardware de IBM tenían poco que ganar y mucho que perder con el éxito de PL/I. El desarrollo del compilador era costoso y los grupos de compiladores de IBM tenían una ventaja competitiva incorporada. Muchos usuarios de IBM deseaban evitar quedar atrapados en soluciones propietarias. Sin soporte inicial para PL/I por parte de otros proveedores, era mejor evitar PL/I.

Evolución del lenguaje PL/I

Este artículo utiliza el estándar PL/I como punto de referencia para las características del lenguaje. Pero una serie de características de importancia en las primeras implementaciones no estaban en el Estándar; y algunos fueron ofrecidos por compiladores que no son de IBM. Y el lenguaje de facto siguió creciendo después del estándar, impulsado en última instancia por los desarrollos en la computadora personal.

Características significativas omitidas del estándar

Multiproceso

Multithreading, bajo el nombre "multitarea", fue implementado por PL/IF, los compiladores PL/I Checkout y Optimization, y los compiladores más nuevos de AIX y Z/OS. Comprendía los tipos de datos EVENT y TASK, la TASK-option en la CALL-statement (Fork), la sentencia-WAIT (Unirse), DELAY(delay-time), EVENT-options en las sentencias de E/S de registro y la Declaración UNLOCK para desbloquear registros bloqueados en archivos EXCLUSIVO. Los datos de eventos identifican un evento en particular e indican si está completo ('1'B) o incompleto ('0'B): los elementos de datos de tareas identifican una tarea (o proceso) en particular e indican su prioridad en relación con otras tareas.

Preprocesador

El primer preprocesador de tiempo de compilación de IBM fue construido por el Centro de Programación Avanzada de IBM Boston ubicado en Cambridge, Massachusetts, y se envió con el compilador PL/IF. La declaración %INCLUDE estaba en el estándar, pero el resto de las funciones no. Los compiladores DEC y Kednos PL/I implementaron prácticamente el mismo conjunto de funciones que IBM, con algunas adiciones propias. IBM ha seguido agregando funciones de preprocesador a sus compiladores. El preprocesador trata el programa fuente escrito como una secuencia de tokens, copiándolos en un archivo fuente de salida o actuando sobre ellos. Cuando se encuentra un token %, se ejecuta la siguiente instrucción de tiempo de compilación: cuando se encuentra un token de identificador y el identificador ha sido DECLAREd, ACTIVATEd, y se le ha asignado un tiempo de compilación valor, el identificador se sustituye por este valor. Los tokens se agregan al flujo de salida si no requieren acción (por ejemplo, +), al igual que los valores de las expresiones de tiempo de compilación ACTIVATEd. Por lo tanto, una variable de tiempo de compilación PI podría declararse, activarse y asignarse usando %PI='3.14159265'. Las apariciones posteriores de PI serían reemplazadas por 3.14159265.

El tipo de datos admitido son DECIMALES FIJOS enteros y CHARACTER cadenas de longitud variable sin longitud máxima. Las declaraciones de estructura son:

y las declaraciones simples, que también pueden tener una [etiqueta-lista:]

La función permitía a los programadores usar identificadores para constantes, p. ej. números de pieza del producto o constantes matemáticas, y fue reemplazada en el estándar por constantes nombradas para datos computacionales. El estándar no admitía la compilación condicional y la generación iterativa de código fuente, posible con funciones de tiempo de compilación. Varios fabricantes implementaron estas instalaciones.

Adiciones a la programación estructurada

Se realizaron adiciones de programación estructurada a PL/I durante la estandarización, pero no se aceptaron en el estándar. Estas características fueron la sentencia-LEAVE para salir de un DO iterativo, la opción-UNTIL y la opción-REPEAT agregado a DO, y una declaración de caso de la forma general: SELECT (expresión) {CUANDO (expresión) grupo}... OTHERWISE grupo
Todas estas características se incluyeron en los compiladores PL/I Checkout y Optimización de IBM y en DEC PL/I.

Instalaciones de depuración

PL/IF había ofrecido algunas funciones de depuración que no se presentaron para el estándar pero que fueron implementadas por otros, en particular el prefijo de condición CHECK (lista de variables), CHECK en condición y SNAP. Los compiladores IBM Optimizing and Checkout agregaron características adicionales apropiadas para el entorno de programación mainframe conversacional (por ejemplo, una condición ATENCIÓN).

Características significativas desarrolladas desde el estándar

Se han realizado varios intentos para diseñar un tipo de miembro de estructura que pudiera tener uno de varios tipos de datos (CELL en los primeros IBM). Con el crecimiento de las clases en la teoría de la programación, se hicieron posibles los enfoques sobre una base PL/I: varios compiladores han agregado UNION, TYPE, etc.

PL/I había sido concebido en un mundo de caracteres de un solo byte. Dado que el soporte para los idiomas japonés y chino se volvió esencial, y los desarrollos en las páginas de códigos internacionales, el concepto de cadena de caracteres se amplió para acomodar cadenas amplias no ASCII/EBCDIC.

El manejo de la hora y la fecha se revisó para solucionar el problema del milenio, con la introducción de la función DATETIME que devolvía la fecha y la hora en uno de los 35 formatos diferentes. Varias otras funciones de fecha se ocupan de las conversiones hacia y desde días y segundos.

Críticas

Problemas de implementación

Aunque el lenguaje es fácil de aprender y usar, implementar un compilador PL/I es difícil y requiere mucho tiempo. Un lenguaje tan grande como PL/I necesitaba subconjuntos que la mayoría de los proveedores pudieran producir y que la mayoría de los usuarios dominaran. Esto no se resolvió hasta que "ANSI G" fue publicado. Las instalaciones de tiempo de compilación, exclusivas de PL/I, supusieron un esfuerzo de implementación adicional y pases de compilación adicionales. Un compilador PL/I era de dos a cuatro veces más grande que los compiladores Fortran o COBOL comparables, y también mucho más lento, supuestamente compensado por las ganancias en la productividad del programador. Esto se anticipó en IBM antes de que se escribieran los primeros compiladores.

Algunos argumentan que PL/I es inusualmente difícil de analizar. Las palabras clave de PL/I no están reservadas, por lo que los programadores pueden usarlas como nombres de variables o procedimientos en los programas. Debido a que el compilador PL/I(F) original intenta la corrección automática cuando encuentra una palabra clave utilizada en un contexto incorrecto, a menudo asume que se trata de un nombre de variable. Esto conduce a "diagnósticos en cascada", un problema resuelto por compiladores posteriores.

El esfuerzo necesario para producir un buen código objeto quizás se subestimó durante el diseño inicial del lenguaje. La optimización del programa (necesaria para competir con la excelente optimización del programa realizada por los compiladores de Fortran disponibles) es inusualmente compleja debido a los efectos secundarios y los problemas generalizados con el aliasing de las variables. La modificación impredecible puede ocurrir de forma asincrónica en los controladores de excepciones, que pueden ser proporcionados por "declaraciones ON" en los llamantes (invisibles). Juntos, estos hacen que sea difícil predecir de manera confiable cuándo se pueden modificar las variables de un programa en tiempo de ejecución. Sin embargo, en el uso típico, los controladores de errores escritos por el usuario (la ON-unit) a menudo no realizan asignaciones a variables. A pesar de las dificultades antes mencionadas, IBM produjo el PL/I Optimizing Compiler en 1971.

PL/I contiene muchas funciones que rara vez se usan, como soporte multitarea (una extensión de IBM para el lenguaje) que agrega costo y complejidad al compilador, y sus instalaciones de coprocesamiento requieren un entorno de programación múltiple con soporte para no- bloqueo de múltiples subprocesos para procesos por parte del sistema operativo. Los escritores de compiladores eran libres de elegir si implementar estas características.

Una variable no declarada, por defecto, se declara por primera vez; por lo tanto, una falta de ortografía puede generar resultados impredecibles. Esta "declaración implícita" no es diferente de los programas FORTRAN. Sin embargo, para PL/I(F), una lista de atributos permite al programador detectar cualquier variable mal escrita o no declarada.

Problemas del programador

Muchos programadores tardaron en pasar de COBOL o Fortran debido a la complejidad percibida del lenguaje y la inmadurez del compilador PL/IF. Los programadores estaban claramente divididos en programadores científicos (que usaban Fortran) y programadores de negocios (que usaban COBOL), con una tensión significativa e incluso disgusto entre los grupos. Sintaxis PL/I tomada de la sintaxis COBOL y Fortran. Entonces, en lugar de notar características que facilitarían su trabajo, los programadores de Fortran de la época notaron la sintaxis de COBOL y opinaron que era un lenguaje comercial, mientras que los programadores de COBOL notaron la sintaxis de Fortran y la consideraron un lenguaje científico.

Tanto los programadores de COBOL como de Fortran lo vieron como un "más grande" versión de su propio idioma, y ambos estaban algo intimidados por el idioma y no estaban dispuestos a adoptarlo. Otro factor fueron las pseudo-similitudes con COBOL, Fortran y ALGOL. Estos eran elementos PL/I que se parecían a uno de esos idiomas, pero funcionaban de manera diferente en PL/I. Tales frustraciones dejaron a muchos programadores experimentados con una visión negativa de PL/I y, a menudo, con una aversión activa por el lenguaje. Uno de los primeros archivos de fortuna de UNIX contenía la siguiente descripción irónica del lenguaje:

Hablando como alguien que ha colado en las complejidades de PL/I, estoy seguro de que sólo Hombres Reales podrían haber escrito un monstruo tan lleno de máquina, agarramiento de ciclos, todo-compasador. ¿Asignar un array y liberar el tercio medio? ¡Claro! ¿Por qué no? Multiply a character string times a bit string and assign the result to a flota decimal? ¡Adelante! Libre un parámetro de procedimiento variable controlado y reallocate antes de pasarlo de vuelta? Superar tres tipos diferentes de variable en la misma ubicación de memoria? ¡Lo que tú digas! ¿Escribir una macro recursiva? Bueno, no, pero los Hombres Reales usan rescan. ¿Cómo podría un lenguaje tan obviamente diseñado y escrito por Real Men no ser destinado para uso del Hombre Real?

En el lado positivo, el soporte completo para punteros a todos los tipos de datos (incluidos los punteros a estructuras), recursividad, multitarea, manejo de cadenas y amplias funciones integradas significaron que PL/I fue un gran avance en comparación con la programación. lenguas de su tiempo. Sin embargo, esto no fue suficiente para persuadir a la mayoría de los programadores o talleres para cambiar a PL/I.

El preprocesador de tiempo de compilación del compilador PL/IF era inusual (fuera del mundo Lisp) en el uso de la sintaxis y la semántica del lenguaje de destino (por ejemplo, en comparación con el preprocesador C& #39;s "#" directivas).

Temas especiales en PL/I

Clases de almacenamiento

PL/I ofrece varias 'clases de almacenamiento' para indicar cómo la vida útil de las variables' el almacenamiento debe administrarse: ESTÁTICO, AUTOMÁTICO, CONTROLADO y BASADO. La más sencilla de implementar es STATIC, que indica que la memoria se asigna e inicializa en el momento de la carga, como se hace en COBOL "working-storage" y Fortran temprano. Este es el valor predeterminado para las variables EXTERNAL. La clase de almacenamiento predeterminada de PL/I para las variables INTERNAL es AUTOMATIC, similar a la de otros lenguajes estructurados en bloques influenciados por ALGOL, como "auto& #34; clase de almacenamiento en lenguaje C y asignación de almacenamiento predeterminada en Pascal y "almacenamiento local" en IBMCOBOL. El almacenamiento para las variables AUTOMATIC se asigna al ingresar al bloque, procedimiento o unidad ON BEGIN en el que se declaran. El compilador y el sistema de tiempo de ejecución asignan memoria para un marco de pila para contenerlos y otra información de mantenimiento. Si una variable se declara con un atributo INITIAL, el código para establecerla en un valor inicial se ejecuta en este momento. Se requiere cuidado para administrar el uso de la inicialización correctamente. Se pueden ejecutar grandes cantidades de código para inicializar variables cada vez que se ingresa un ámbito, especialmente si la variable es una matriz o estructura. El almacenamiento de variables AUTOMATIC se libera al salir del bloque: las variables STATIC, CONTROLLED o BASED se utilizan para retener variables& #39; contenidos entre invocaciones de un procedimiento o bloque. El almacenamiento CONTROLADO también se gestiona mediante una pila, pero el programador gestiona la inserción y extracción de asignaciones en la pila mediante ALLOCATE y FREE declaraciones. El almacenamiento de las variables BASED se administra mediante ALLOCATE/FREE, pero en lugar de una pila, estas asignaciones tienen una duración independiente y se gestionan a través de OFFSET variables o POINTER.

El atributo AREA se utiliza para declarar montones definidos por el programador. Los datos se pueden asignar y liberar dentro de un área específica, y el área se puede borrar, leer y escribir como una unidad.

Compartir tipo de almacenamiento

Hay varias formas de acceder al almacenamiento asignado a través de diferentes declaraciones de datos. Algunos de estos están bien definidos y son seguros, algunos se pueden usar de manera segura con una programación cuidadosa y algunos son intrínsecamente inseguros y/o dependientes de la máquina.

Pasar una variable como argumento a un parámetro por referencia permite que se haga referencia al almacenamiento asignado del argumento mediante el parámetro. El atributo DEFINED (por ejemplo, DCL A(10,10), B(2:9,2:9) DEFINED A) permite que parte o la totalidad de una variable' s de almacenamiento para ser utilizado con una declaración diferente, pero coherente. La definición del idioma incluye un atributo CELL (más tarde renombrado como UNION) para permitir que diferentes definiciones de datos compartan el mismo almacenamiento. Esto no fue compatible con muchos de los primeros compiladores de IBM. Estos usos son seguros e independientes de la máquina.

La E/S de registros y el procesamiento de listas producen situaciones en las que el programador necesita ajustar una declaración al almacenamiento del siguiente registro o elemento, antes de saber qué tipo de estructura de datos tiene. Las variables basadas y los punteros son clave para este tipo de programas. Las estructuras de datos deben diseñarse de forma adecuada, normalmente utilizando campos en una estructura de datos para codificar información sobre su tipo y tamaño. Los campos se pueden mantener en la estructura anterior o, con algunas restricciones, en la actual. Cuando la codificación se encuentra en la estructura anterior, el programa debe asignar una variable basada con una declaración que coincida con el elemento actual (utilizando expresiones para las extensiones cuando sea necesario). Cuando la información de tipo y tamaño se mantenga en la estructura actual ("estructuras autodefinidas"), los campos que definen el tipo deben estar delante de los elementos dependientes del tipo y en el mismo lugar en cada versión de los datos. estructura. La opción REFER se utiliza para extensiones autodefinidas (por ejemplo, longitudes de cadena como en DCL 1 A BASADO, 2 N BINARIO, 2 B CHAR(LENGTH REFER A.N.), etc. – donde LENGTH se usa para asignar instancias de la estructura de datos. Para estructuras autodefinidas, cualquier campo de escritura y REFERED se coloca delante del "real&#34 Si los registros en un conjunto de datos, o los elementos en una lista de estructuras de datos, están organizados de esta manera, pueden manejarse de manera segura e independiente de la máquina.

Las implementaciones de PL/I (a excepción del compilador PL/I Checkout) no realizan un seguimiento de la estructura de datos utilizada cuando se asigna el almacenamiento por primera vez. Cualquier declaración BASED se puede usar con un puntero en el almacenamiento para acceder al almacenamiento, intrínsecamente inseguro y dependiente de la máquina. Sin embargo, este uso se ha vuelto importante para la "aritmética de punteros" (típicamente agregando una cierta cantidad a una dirección conocida). Este ha sido un tema polémico en informática. Además del problema de las referencias salvajes y los desbordamientos del búfer, surgen problemas debido a la alineación y la longitud de los tipos de datos utilizados con compiladores y máquinas particulares. Muchos casos en los que podría ser necesaria la aritmética de punteros implican encontrar un puntero a un elemento dentro de una estructura de datos más grande. La función ADDR calcula dichos punteros, de forma segura e independiente de la máquina.

La aritmética de punteros se puede lograr creando un alias de una variable binaria con un puntero como en
PUNTERO DCL P, N BINARIO FIJO(31) BASADO(DIRECCIÓN(P)); N=N+255;
Se basa en que los punteros tienen la misma longitud que los enteros FIXED BINARY(31) y están alineados en los mismos límites.

Con el predominio de C y su actitud libre y sencilla hacia la aritmética de punteros, los compiladores IBM PL/I recientes permiten que los punteros se utilicen con los operadores de suma y resta para brindar la sintaxis más simple (pero las opciones del compilador pueden rechazar estas prácticas donde la seguridad y la independencia de la máquina son primordiales).

Unidades ON y manejo de excepciones

Cuando se diseñó PL/I, los programas solo se ejecutaban en modo por lotes, sin intervención posible del programador en una terminal. Una condición excepcional como la división por cero abortaría el programa produciendo solo un volcado hexadecimal del núcleo. El manejo de excepciones PL/I, a través de unidades ON, permitió que el programa mantuviera el control frente a excepciones de hardware o sistema operativo y recuperara la información de depuración antes de cerrarse con más gracia. A medida que un programa se depuraba correctamente, la mayor parte del manejo de excepciones podía eliminarse o deshabilitarse: este nivel de control se volvió menos importante cuando la ejecución conversacional se convirtió en un lugar común.

El manejo de excepciones computacionales se habilita y deshabilita mediante prefijos de condición en sentencias, bloques (incluidas las unidades ON) y procedimientos. - p.ej. (TAMAÑO, NOSUBSCRIPTRANGE): A(I)=B(I)*C; . Las excepciones del sistema operativo para Entrada/Salida y administración de almacenamiento siempre están habilitadas.

La unidad ON es una sentencia única o bloque BEGIN introducido por una sentencia ON. Ejecutar la instrucción ON habilita la condición especificada, por ejemplo, ON ZERODIVIDE ON-unit. Cuando ocurre la excepción para esta condición y la condición está habilitada, se ejecuta la unidad ON para la condición. Las unidades ON se heredan a lo largo de la cadena de llamadas. Cuando se activa un bloque, procedimiento o unidad ON, las unidades ON establecidas por la activación invocadora son heredadas por la nueva activación. Pueden ser anulados por otra sentencia ON y pueden ser restablecidos por la sentencia REVERT. La excepción se puede simular utilizando la declaración SIGNAL, p. para ayudar a depurar los controladores de excepciones. El principio de herencia dinámica para unidades ON permite que una rutina maneje las excepciones que ocurren dentro de las subrutinas que usa.

Si ninguna unidad ON está en efecto cuando se genera una condición, se toma una acción estándar del sistema (a menudo esto es para generar la condición ERROR). La acción del sistema se puede restablecer utilizando la opción SYSTEM de la sentencia ON. Con algunas condiciones, es posible completar la ejecución de una unidad ON y volver al punto de interrupción (por ejemplo, STRINGRANGE, UNDERFLOW, CONVERSION, OVERFLOW, AREA y FILE) y reanudar la ejecución normal. Con otras condiciones como (SUBSCRIPTRANGE), se genera la condición ERROR cuando se intenta. Una unidad ON se puede terminar con un GO TO que evita el regreso al punto de interrupción, pero permite que el programa continúe ejecutándose en otro lugar según lo determine el programador.

Una unidad ON debe diseñarse para manejar las excepciones que ocurren en la propia unidad ON. La declaración ON ERROR SYSTEM; permite una trampa de error anidada; si ocurre un error dentro de una unidad ON, el control podría pasar al sistema operativo donde podría producirse un volcado del sistema o, para algunas condiciones computacionales, continuar la ejecución (como se mencionó anteriormente).

Las sentencias de E/S RECORD de PL/I tienen una sintaxis relativamente simple, ya que no ofrecen opciones para muchas situaciones, desde el final del archivo hasta los errores de transmisión de registros que pueden ocurrir cuando un registro es leído o escrito. En su lugar, estas complejidades se manejan en las unidades ON para las diversas condiciones de archivo. Se adoptó el mismo enfoque para la subasignación AREA y la condición AREA.

La existencia de unidades ON de manejo de excepciones puede tener un efecto en la optimización, porque las variables se pueden inspeccionar o modificar en unidades ON. Es posible que los valores de las variables que de otro modo se mantendrían en registros entre sentencias, deban devolverse al almacenamiento entre sentencias. Esto se discute en la sección anterior sobre Cuestiones de implementación.

IR A con un objetivo no fijo

PL/I tiene equivalentes para las instrucciones GO TO especializadas de COBOL y FORTRAN.

Existe sintaxis para COBOL y FORTRAN para codificar dos tipos especiales de GO TO, cada uno de los cuales tiene un objetivo que no siempre es el mismo.

PL/I tiene variables de etiqueta de sentencia (con el atributo LABEL), que pueden almacenar el valor de una etiqueta de sentencia y luego usarse en una sentencia GOTO.

LABL1:...
.
.
LABL2:...
.
.
.
MY_DEST = LABL1;
.
Vayan a My_DEST;
AQUI (LUCKY_NUMBER); /* menos 1, cero, o... */

AQUI(-1): PUT LIST ("I O U"); GO TO Lottery;
AQUI(0): PUT LIST ("No efectivo"); GO TO Lottery;
AQUI (1): PUT LIST ("Dollar Bill"); GO TO Lottery;
AQUI (2): PUT LIST ("TWO DOLLARS"); GO TO Lottery;

Las variables de etiqueta de declaración se pueden pasar a los procedimientos llamados y se pueden usar para regresar a una declaración diferente en la rutina de llamada.

Programas de muestra

Programa hola mundo

Hola2: proc opciones()principal); # lista ()¡Hola, Mundo! ');final Hola2;

Buscar una cadena

/* Lea en una línea, que contiene una cadena,/* y luego imprimir cada línea posterior que contiene esa cadena. */find_strings: procedimiento opciones ()principal); Declara patrón carácter ()100) variable; Declara línea carácter ()100) variable; Declara line_no fijo binario; on endfile ()Sysin) Para; # edición ()patrón) ()L); line_no = 1; do para siempre; # edición ()línea) ()L); si índice()línea, patrón)  0 entonces # Patrón lista ()line_no, línea); line_no = line_no + 1; final;final find_strings;