Nuestra web


El compilador de Pascal P4

Josep Maria Blasco

Resumen

A principios de 1980, el Laboratorio de Cálculo de la Universitat de Barcelona (UB), del que soy colaborador desde 1978, recibe una cinta conteniendo el compilador Pascal P4 desarrollado por estudiantes de Niklaus Wirth en el ETH Zurich. Me encargo, en mi tiempo libre, sin retribución alguna, y mientras continúo mis estudios de Matemáticas, del proyecto de implementar en lenguaje ensamblador un run-time para el compilador, al principio en un IBM/360 modelo 40 que se programaba con fichas perforadas y después con un más moderno IBM 4341. Hacia finales de 1981 la implementación está completa: es el primer compilador de Pascal de que dispone la UB. Con él se dan a principios de 1982 los primeros cursos sobre ese lenguaje, en aquel entonces novedoso.

Nota: Se puede encontrar una versión resumida de lo relatado aquí en la entrevista que me hizo Andreu Veà para el proyecto WiWiW, publicada en Cómo creamos Internet (Ed. Península, Barcelona, 2013), pp. 454-5. La entrevista está disponible en pdf (3.4 MB), y puede también consultarse una versión de trabajo de la misma, posiblemente más actualizada, en html.

Contenido

Prehistoria: 1977-1979

Introducción: PL/I (1977-78)

Es 1977, y tengo 17 años. Empiezo mis estudios de Matemáticas en la Universitat de Barcelona (UB). Durante el primer semestre de la asignatura de Cálculo Numérico nos enseñan a programar en PL/I, como preparación para abordar algunos problemas sencillos (p. ej., el método de Newton-Raphson) durante la segunda parte del curso. Es mi primer contacto con un ordenador. Las otras asignaturas me interesan de un modo muy relativo; programar, en cambio, me parece absolutamente fascinante. Para alguien con sensibilidad matemática, que uno pueda escribir algo parecido a una fórmula y que una máquina lo realice es realmente extraordinario: ¡hay máquinas que hacen reales las Matemáticas! Hoy día puede parecer una tontería, ya que todo el mundo lo da por sentado, pero en ese momento me asombra que un artefacto pueda, de algún modo, traspasar la barrera entre el universo platónico de los objetos matemáticos y la realidad material.

//JOB YCNB014A 

Los programas se escribían en tarjetas perforadas, y los resultados se entregaban en papel pijama. Cada programa iba precedido por una ficha especial de color rosado que identificaba al alumno. Mi identificador era "YCNB014".

Me propongo aprenderlo todo sobre el PL/I. En esa época no es fácil conseguir manuales; uno se tiene que apañar con lo que cuentan en clase, pero en clase sólo explican lo necesario para la asignatura. Le pido al profesor que me preste "el" manual (sí, sólo hay uno en toda la UB), lo fotocopio al 50%, que es para lo que me da el presupuesto, y empiezo a llevarlo encima todo el día y a leerlo continuamente — a leer pulsionalmente, diría ahora. En cuanto tengo un rato libre, aprovecho para leer una páginas. Leo mientras espero el autobus, mientras espero a los amigos, entre clase y clase...

Colaborador del Laboratorio de Cálculo (1978)

A finales de la temporada 1977-78, con 18 años, domino realmente el lenguaje, y el profesor de la asignatura, Joan Llopart, que además es jefe de Sistemas y Explotación del Laboratorio de Cálculo de la UB, piensa que es una lástima que una persona con tanta capacidad no pueda seguir usando el ordenador (según el currículum de la carrera no tengo oportunidad de volver a usarlo hasta quinto), y me nombra Colaborador del Laboratorio. Es una figura extinguida y vacía de contenido, pero me permite usar el ordenador, pasando por detrás de los demás usuarios, siempre que lo necesite.

Escrito de Joan Llopart de 1982 en el que aparece mencionada mi vinculación como Colaborador con el Laboratorio de Cálculo (pdf, 1 MB).

ASSEMBLER/360 y el DOS PL/I Optimizing Compiler: Execution Logic (1978-1979)

Septiembre de 1978. He terminado primero de carrera y estoy por comenzar segundo. Acabo de cumplir los 18 años: mayor de edad. Me encuentro con que soy "Colaborador" del Laboratorio de Cálculo. Es una situación ideal: no tengo jefes ni empleados, ni proyecto, ni fechas de entrega. No tengo muchos derechos (mis programas siempre pasan los últimos), pero tampoco tengo ninguna obligación: como no cobro, ni se les ocurre darme trabajo (estamos hablando de 1978, hoy sería distinto). Puedo dedicarme a aprender en serio, sin proyectos inventados por otro, sin plazos, sin exámenes.

Diploma del Curso de Programador en Aplicaciones Científicas (1981: pdf, 513 KB).

Me apunto al "Curso de Programador en Aplicaciones Científicas" del Laboratorio de Cálculo. Continúo estudiando PL/I: quiero saber cómo está hecho "por dentro". Cae en mis manos el manual DOS PL/I Optimizing Compiler: Execution Logic, que lo explica. Pruebo cosas: paso un vector a una rutina externa, y en la rutina externa declaro que el argumento es un pointer; la estructura a la que apunta el pointer es el control block del vector, tal como se describe en el Execution Logic. Cambio un valor de esa estructura, y retorno: ¡el vector ha cambiado de tamaño! Decido aprender ASSEMBLER/360, arquitectura 360 y lenguaje máquina. PL/I usa dos librerías para los ejecutables que genera: la Resident Library, con las rutinas de tiempo de ejecución enlazadas estáticamente y, para ahorrar memoria, la Transient Library, con rutinas que se cargan a medida que se necesitan. La rutina transient IBMDPIR es la encargada de inicializar el run-time de PL/I; pido un volcado hexadecimal, y la desensamblo a mano (1000 lineas de código). Después aplico ingeniería inversa y reconstruyo la lógica. Descubro que hay una constante que reserva espacio para los buffers de la interfaz PL/I-FORTRAN, que había dejado de funcionar desde hacía tiempo y no se podía arreglar, porque el ordenador (y con ello el software) estaba descatalogado. Cambio la constante, ampliando el espacio, ensamblo la rutina modificada y la pruebo: ¡la interfaz entre PL/I y FORTRAN vuelve a funcionar! De este modo apruebo la asignatura de Representación Gráfica del Curso de Programador.

Historia: 1980-1982

Pascal P4: La cinta del ETH Zurich

Principios de 1980. Estoy cursando tercer año de Matemáticas y el "Curso de Analista en Aplicaciones Científicas" del Laboratorio de Cálculo, y tengo 19 años.

Diploma del Curso de Analista en Aplicaciones Científicas (1981: pdf, 511 KB).

Llega al Laboratorio una cinta del ETH Zurich con un compilador de Pascal, Pascal P4, de la serie Pascal P desarrollado por Urs Ammann, Kesav Nori y Christian Jacobi, alumnos de Niklaus Wirth. Joan Llopart convoca una reunión para ver qué hacemos con la cinta. Nos presentamos voluntarios para examinarla el propio Joan, otra persona y yo, y quedamos en vernos al cabo de 15 días para decidir qué hacemos con la cinta: el lenguaje Pascal da mucho que hablar, y sería fantástico poder contar con un compilador para probarlo. A los 15 días he diseñado un plan trienal para la implementación del compilador, y las otras dos personas han estado ocupadas en otras cosas. Me quedo el proyecto yo.

El primer problema es leer la cinta: ha sido escrita en un CDC 6000 y, para máxima compatibilidad con distintos sistemas, está codificada en un subconjunto de seis bits de ASCII (es decir, no hay letras minúsculas, algunos carácteres comunes están codificados, por ejemplo "[" se representa como "(.", etcétera). Decido leerla en PL/I usando un vector de BIT(6) UNALIGNED. La cinta contiene:

  • PCOM, un compilador de Pascal P4 a P-code escrito en Pascal P4 (en seguida veremos qué es el P-code).
  • PINT, un intérprete de P-code escrito en Pascal P4.
  • El resultado de compilar PCOM con PCOM (es decir, un compilador de Pascal P4 escrito en P-code), que llamaremos BIN.

El P-code resulta ser el ensamblador de una máquina que no existe. La intención es que los que reciben la cinta usen el PINT, que define de modo inambiguo la semántica del P-code, como base para escribir a) una máquina virtual que implemente la arquitectura P-Code, o b) escriban un generador de código (es decir, un compilador de P-Code a lenguaje máquina). Se noterá que la opción a), que hoy día se da por sentada (por ejemplo, las implementaciones de Java están basadas en máquinas virtuales) era en aquel momento muy novedosa. Tengo que tomar una serie de decisiones de diseño.

Decisiones de diseño

Me decanto por la opción a): voy a escribir un intérprete de P-code. Lo voy a hacer en ASSEMBLER, casi no tenemos memoria: no olvidemos que el objetivo es poder compilar con PCOM programas complejos, por ejemplo PCOM. Para hacer todo esto, necesito:

  1. Crear un ensamblador de P-Code a alguna representación binaria (fácil).
  2. Escribir el emulador de la versión binaria de P-Code. Esto incluye:
    1. Escribir el nucleo central del intérprete, el que implementa la pila, las operaciones aritméticas, etc (tedioso).
    2. Escribir la parte del intérprete que se conecta con el "mundo exterior": entrada/salida, etc (problemático).

La parte más complicada es 2.b, específicamente: ¿cómo probar las partes de un run-time, y asegurarse de que funcionan, si todavía no se dispone de las demás partes, y todo está relacionado? Pongo en acción aquí mis conocimientos sobre la arquitectura interna del PL/I, y decido que el run-time de Pascal va a compartir con el de PL/I tantos elementos como sea necesario como para que sea posible probar las distintas rutinas del run-time de Pascal desde un programa PL/I: esto me facilitará mucho las cosas. Declaro las rutinas que voy escribiendo como ENTRY EXTERNAL OPTIONS(ASSEMBLER), y defino una Task Communications Area (TCA) como la usada en PL/I; supongo, como en PL/I, que R12 apunta a la TCA. De este modo puedo ir escribiendo las piezas del run-time y probarlas desde PL/I antes de tener el todo terminado.

Lenguajes

Un amigo me habla de la Facultat d'Informàtica de Barcelona (FIB): tienen un ordenador con pantallas. Visito el ordenador y me saco un código. Charlo con Pere Botella, entonces de la FIB, y me pregunta si quiero dar clases de programación. Le explico que estoy cursando tercero: cuando termine la carrera podré hacerlo. Entro en contacto con una serie de revistas que describen nuevos lenguajes: Alphard, CLU, Modula-2, Ada, ...

VM/370

Mientras estoy escribiendo el intérprete, cambia el director del Laboratorio de Cálculo. Ahora es Carles Simó, que debe tener unos 34 años. Se compra un nuevo ordenador: un IBM 4341 con pantallas 3270 y sistema operativo VM/370 BSEPP con CMS. El modelo de entrada/salida de CMS es distinto del de DOS, pero con pocos cambios adapto el run-time. Ahora todo va infinitamente más rápido: el sistema es multi-usuario y no hay que hacer cola para que pase tu programa, hay editores de pantalla completa en vez de fichas, etc.

Una terminal 3277.

Los primeros bootstraps (1981)

Es 1981. Tengo 21 años, y estoy terminando la carrera. El run-time está completo. Ensamblo y ejecuto BIN: ¡ya tenemos compilador de Pascal P4! Ahora viene la prueba de fuego: compilo PCOM con el nuevo compilador; el resultado es una copia perfecta de BIN. Esto demuestra que la implementación es correcta.

Ahora se trata de ir mejorando el compilador. PCOM implementa Pascal P4, que tiene serias limitaciones. Utilizo el proceso de bootstrap, que ilustraré con un ejemplo. Partamos de PCOM, que implementa Pascal P4 puro, y supongamos que quiero ampliar el lenguaje para que se admita la opción ELSIF en la instrucción IF. Modifico PCOM para que admita esa sintaxis; llamemos PCOM' al resultado. PCOM' es un compilador de Pascal P4 modificado escrito en Pascal P4 puro. Compilo PCOM' con PCOM y obtengo BIN'. Ejecuto BIN' y lo pruebo. Si he hecho las cosas bien, BIN' compila el lenguaje modificado. Reescribo ahora PCOM' en el lenguaje modificado; llamemos al resultado PCOM”. PCOM” es un compilador del lenguaje modificado escrito en el lenguaje modificado. Compilo PCOM” con BIN', y obtengo BIN”. Si ahora compilo PCOM” con BIN” y vuelvo a obtener BIN”, todo está bien (en algunos casos puede ser necesario modificar también el P-Code, pero la idea y el procedimiento son los mismos).

Aplico el proceso de bootstrap varias veces, para ir añadiendo nuevas funcionalidades al lenguaje. El documento de Joan Llopart mencionado al principio lista, "entre otras", las siguientes modificaciones a 12 de julio de 1982:

  • La instrucción LOOP ... EXIT IF ... END.
  • La instrucción IF admite ELSIF.
  • Las tiras de carácteres se pueden encerrar en comillas simples o dobles.
  • El compilador acepta símbolos &, | , ¬, {, }, (. , .) como sinónimos de AND, OR, NOT, (* , *), [ , ].
  • Pueden leerse tiras de carácteres (array of char) con el procedimiento READ.
  • Se pueden leer y escribir variables de tipos escalares enumerativos.
  • Se pueden realizar entradas con formato análogas a las salidas con formato.
  • Se suprime la limitación de que el tipo de resultado de una función tenga que ser escalar, subrango o pointer.
  • El compilador distingue entre los símbolos ":" y "..".
  • La instrucción CASE admite la opción OTHERS.
  • Diferentes objetos de utilidad general y de programación de sistemas (interfaces con los parámetros de sistema, códigos de retorno, funciones para obtener el tiempo de CPU utilizado, la fecha o la hora, etc.).

Los primeros cursos (1982)

Ahora el Laboratorio de Cálculo ya dispone de un compilador de Pascal, y puede ofertar una asignatura de Pascal en el Curso de Programador. Imparto esa asignatura y también un curso en el Institut de Ciències de l'Educació (10 sesiones, del 3 de mayo al 2 de junio). Cumplo 22 años mientras estoy dando este último curso, en junio termino la carrera, y en septiembre me incorporo como profesor de programación en la Facultat d'Informàtica de Barcelona.

Folleto del "Curs d'Introducció al Pascal: Un llenguatge orientat a la programació estructurada" organizado por Institut de Ciències de l'Educació (pdf, 1.5 MB).

Copyright © EPBCN, 1996-2024.