POP-2 (también llamado POP2 ) es un lenguaje de programación desarrollado alrededor de 1970 a partir del lenguaje anterior POP-1 (desarrollado por Robin Popplestone en 1968, originalmente llamado COWSEL ) por Robin Popplestone y Rod Burstall en la Universidad de Edimburgo . Se basó en muchas fuentes: los lenguajes Lisp y ALGOL 60 , y las ideas teóricas de Peter J. Landin . Utilizaba un compilador incremental , que le daba algo de la flexibilidad de un lenguaje interpretado , incluyendo la posibilidad de nuevas definiciones de funciones en tiempo de ejecución y la modificación de definiciones de funciones mientras se ejecuta un programa (ambas son características de la compilación dinámica ), sin la sobrecarga de un lenguaje interpretado. [1]
La sintaxis de POP-2 es similar a ALGOL , excepto que las asignaciones están en orden inverso: en lugar de escribir
un := 3;
uno escribe
3 -> un;
La razón de esto es que el lenguaje tiene una noción explícita de pila de operandos . Por lo tanto, la asignación previa se puede escribir como dos instrucciones separadas :
3;
que evalúa el valor 3 y lo deja en la pila, y
-> un;
que extrae el valor superior de la pila y lo asigna a la variable 'a'. De manera similar, la llamada a la función
f(x, y, z);
se puede escribir como
x, y, z; f();
(las comas y los puntos y comas son en gran medida intercambiables) o incluso
x, y, zf;
o
(x, y, z).f;
Debido al paradigma basado en pilas , no hay necesidad de distinguir entre declaraciones y expresiones ; por lo tanto, las dos construcciones
Si a > b entonces c -> e demás d -> e cerca;
y
Si a > b entonces do demás d cerrar -> e;
son equivalentes (el uso de close
, como aún endif
no se había convertido en una end-of-if-clause
notación común).
No existen construcciones de lenguaje especiales para crear matrices o estructuras de registros como se entienden comúnmente: en cambio, se crean con la ayuda de funciones integradas especiales, por ejemplo, newarray
[2] (para matrices que pueden contener cualquier tipo de elemento) y newanyarray
[3] para crear tipos restringidos de elementos.
Por lo tanto, los accesores de campo de registro y de elemento de matriz son simplemente casos especiales de una función doble : se trata de una función que tenía otra función adjunta como su actualizador , [4] que se llama en el lado receptor de una asignación. Por lo tanto, si la variable a
contiene una matriz, entonces
3 -> a(4);
es equivalente a
actualizador(a)(3, 4);
La función incorporada updater
que devuelve el actualizador del doblete. Por supuesto, updater
es un doblete y se puede utilizar para cambiar el componente actualizador de un doblete.
Las variables pueden contener valores de cualquier tipo, incluidas las funciones, que son objetos de primera clase. Por lo tanto, las siguientes construcciones
función max xy; si x > y entonces x de lo contrario y cierra fin;
y
vars máx; lambda xy; si x > y entonces x de lo contrario y cierra fin -> máx;
son equivalentes
Una operación interesante sobre funciones es la aplicación parcial (a veces denominada currying ). En la aplicación parcial, una cierta cantidad de los argumentos más a la derecha de la función (que son los últimos que se colocan en la pila antes de que se involucre la función) se congelan en valores dados, para producir una nueva función con menos argumentos, que es un cierre de la función original. Por ejemplo, considere una función para calcular polinomios generales de segundo grado:
función poly2 xabc; a * x * x + b * x + c fin;
Esto se puede limitar, por ejemplo, como
vars menos1cuadrado; poly2(% 1, -2, 1%) -> menos1cuadrado;
de tal manera que la expresión
menos1cuadrado(3)
aplica el cierre de poly2 con tres argumentos congelados, al argumento 3, devolviendo el cuadrado de (3 - 1), que es 4. La aplicación de la función parcialmente aplicada hace que los valores congelados (en este caso 1, -2, 1) se agreguen a lo que ya esté en la pila (en este caso 3), después de lo cual se invoca la función original poly2. Luego usa los cuatro elementos superiores de la pila, produciendo el mismo resultado que
poli2(3, 1, -2, 1)
es decir
1*3*3 + (-2)*3 + 1
En POP-2 fue posible definir nuevas operaciones (operadores en términos modernos). [5]
operación vars 3 +*; lambda xy; x * x + y * y fin -> no operativo +*
La primera línea declara una nueva operación +* con precedencia (prioridad) 3. La segunda línea crea una función f(x,y)=x*x+y*y, y la asigna a la operación recién declarada +*.
La versión original de POP-2 se implementó en una computadora Elliott 4130 en la Universidad de Edimburgo (con solo 64 KB de RAM, duplicada a 128 KB en 1972). [6]
POP-2 fue portado a la serie ICT 1900 en un 1909 en la Universidad de Lancaster por John Scott en 1968.
A mediados de la década de 1970, POP-2 fue portado a BESM-6 (Sistema POPLAN).
En 1978, Hamish Dewar implementó una versión de POP-2 específicamente para que la usaran los estudiantes de grado de la Universidad de Edimburgo en la clase de IA2 (Inteligencia Artificial, nivel de segundo año) utilizando el sistema operativo EMAS . Esta implementación se escribió desde cero en el lenguaje de programación de Edimburgo, IMP . [7]
Se implementaron versiones posteriores para Computer Technology Limited (CTL) Modular One, PDP-10 , serie ICL 1900 (que ejecutaba el sistema operativo George ). Julian Davies, en Edimburgo, implementó una versión extendida de POP-2, a la que llamó POP-10 en la computadora PDP-10 que ejecutaba TOPS-10 . Este fue el primer dialecto de POP-2 que trataba las mayúsculas y minúsculas como importantes en los nombres de los identificadores, usaba minúsculas para la mayoría de los identificadores del sistema y admitía identificadores largos con más de 8 caracteres.
Poco después, Robert Rae y Allan Ramsay implementaron en Edimburgo una nueva implementación conocida como WPOP (por WonderPop), en un proyecto financiado por un consejo de investigación. Esa versión introdujo espacios de direcciones enjaulados, cierta tipificación sintáctica en tiempo de compilación (por ejemplo, para números enteros y reales) y algunas construcciones de coincidencia de patrones para su uso con una variedad de estructuras de datos .
Paralelamente, Steve Hardy, de la Universidad de Sussex , implementó un subconjunto de POP-2, al que llamó POP-11, que se ejecutaba en una computadora PDP-11/40 de Digital Equipment Corporation (DEC). Originalmente, se diseñó para ejecutarse en el sistema operativo RSX-11D de DEC, en modo de tiempo compartido para la enseñanza, pero eso causó tantos problemas que se instaló y utilizó una versión anterior de Unix en su lugar. Esa versión de Pop-11 estaba escrita en lenguaje ensamblador de Unix y el código se compilaba de forma incremental a un bytecode intermedio que se interpretaba. Ese puerto se completó alrededor de 1976 y, como resultado, Pop-11 se utilizó en varios lugares para la enseñanza. Para respaldar su función de enseñanza, se modificaron muchas de las características sintácticas de POP-2, por ejemplo, reemplazando function ... end
y define ... enddefine
agregando una variedad más amplia de construcciones de bucle con corchetes de cierre para que coincidan con sus corchetes de apertura en lugar del uso de close
bucles for all en POP-2. Pop-11 también introdujo un comparador de patrones para estructuras de lista, lo que hizo mucho más fácil enseñar programación de inteligencia artificial (IA).
Alrededor de 1980, Pop-11 fue portado a una computadora VAX-11/780 por Steve Hardy y John Gibson, y poco después fue reemplazado por un compilador incremental completo (que produce código de máquina en lugar de un código intermedio interpretado). La existencia del compilador y todas sus subrutinas en tiempo de ejecución hicieron posible soportar extensiones de lenguaje mucho más ricas que las que son posibles con Macros, y como resultado Pop-11 fue utilizado (por Steve Hardy, Chris Mellish y John Gibson) para producir una implementación de Prolog , utilizando la sintaxis estándar de Prolog, y el sistema combinado se conoció como Poplog , al que se agregaron Common Lisp y Standard ML más tarde. Esta versión fue posteriormente portada a una variedad de máquinas y sistemas operativos y, como resultado, Pop-11 se convirtió en el dialecto dominante de POP-2, todavía disponible en el sistema Poplog.
Alrededor de 1986, una nueva empresa de inteligencia artificial, Cognitive Applications Ltd., colaboró con miembros de la Universidad de Sussex para producir una variante de Pop-11 llamada AlphaPop que se ejecutaba en computadoras Apple Mac , con gráficos integrados. Esta se utilizó para muchos proyectos comerciales y para enseñar programación de inteligencia artificial en varias universidades. El hecho de que se implementara en un dialecto temprano de C, utilizando un compilador idiosincrásico, hizo que fuera muy difícil de mantener y actualizar a nuevas versiones del sistema operativo Mac. Además, AlphaPop no era " limpio de 32 bits " debido al uso de bits de dirección altos como bits de etiqueta para indicar el tipo de objetos, lo que era incompatible con el uso de memoria por encima de los 8 Mb en las Macintosh posteriores.