Story Transcript
Cap´ıtulo 5
Lenguajes de programaci´ on 5.1 5.2 5.3 5.4 5.5
Lenguajes de bajo y alto nivel . . . . . . . . . Descripci´on de los lenguajes de programaci´ on Procesadores de lenguajes . . . . . . . . . . . Ejercicios . . . . . . . . . . . . . . . . . . . . Comentarios bibliogr´ aficos . . . . . . . . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
120 131 141 148 149
Un lenguaje de programaci´ on es un lenguaje artificial, dise˜ nado para representar expresiones e instrucciones de forma inteligible para las computadoras. Los lenguajes de programaci´ on son, en gran medida, comparables a los lenguajes naturales: sus s´ımbolos b´ asicos constituyen su alfabeto, y con ellos se construye el vocabulario del lenguaje, cuyos elementos se llaman tokens. Estos tokens se combinan de acuerdo con las reglas sint´ acticas del lenguaje, formando expresiones y sentencias cuyo significado viene dado por la sem´ antica del lenguaje. Los lenguajes de programaci´ on son sin embargo considerablemente m´as simples que los naturales en su sintaxis y, especialmente, en su sem´antica. En este cap´ıtulo se introducen distintos aspectos relacionados con los lenguajes de programaci´ on. En primer lugar, hacemos una presentaci´on evolutiva, mostrando las aportaciones hechas por los lenguajes
120
´n Cap´ıtulo 5. Lenguajes de programacio
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 ????
direcci´on ... 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 ???? ...
0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101
0010 0000 0101 1100 0000 0101 0001 1101 0011 1110 0000 ????
contenido ... 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 ???? ???? ...
1101 1100 1101 1010 1101 1100 1101 0011 1101 ???? 1010 ????
Figura 5.1. Expresi´ on de un programa en c´ odigo m´ aquina.
ensambladores y los de alto nivel y muy alto nivel, fuertemente orientados al problema. La descripci´ on de los lenguajes de programaci´ on se efect´ ua, cada vez en mayor medida, a trav´es de procedimientos formales, evit´ andose toda ambig¨ uedad y facilitando el estudio de las propiedades de los programas, por lo que estudiamos algunos de esos procedimientos. Finalmente, presentamos los programas procesadores de lenguajes, su funci´ on, sus tipos y los entornos de programaci´ on, muy evolucionados, que facilitan hoy d´ıa las distintas fases de desarrollo de programas.
5.1 5.1.1
Lenguajes de bajo y alto nivel Lenguajes orientados a la m´ aquina
Hablando estrictamente, los u ´nicos s´ımbolos que comprenden los computadores son dos: el cero y el uno. Combin´ andolos apropiadamente, se forman las instrucciones, como se ha descrito en el cap´ıtulo 3. La interpretaci´ on de estas instrucciones est´a dirigida a componentes f´ısicos de la m´aquina subyacente, tales como el registro acumulador o
5.1. Lenguajes de bajo y alto nivel
dir.
m1
m2 d n
121
contenido ... IN n CAR d RES n COND m2 CAR n RES d ALM n GOTO m1 OUT n END 10 ? ...
Figura 5.2. Un programa en lenguaje ensamblador
las direcciones de los operandos. Por estas razones tan obvias, estos rudimentarios lenguajes se llaman lenguajes orientados a la m´ aquina o, m´as brevemente, lenguajes de m´aquina. El programa de la figura 5.1 est´ a escrito en el lenguaje m´aquina definido en el cap´ıtulo 3. Resulta evidente que, aun siendo los lenguajes m´ aquina el medio de expresi´on natural para las computadoras, son ciertamente aparatosos para el programador humano que deba redactarlos, leer o modificar los programas escritos en ellos. Presentan adem´as el inconveniente de no ser transportables, esto es, no ser comprendidos por m´aquinas diferentes. Los lenguajes evolucionados han surgido para superar estas deficiencias. El primer paso para hacer m´ as humana la programaci´ on consisti´ o en introducir el uso de identificadores nemot´ecnicos para referir instrucciones y nombrar las direcciones de los operandos mediante s´ımbolos en lugar de hacerlo mediante sus c´odigos binarios. Nacen as´ı los primeros lenguajes simb´ olicos. El programa de la figura 5.1 podr´ıa traducirse a
122
´n Cap´ıtulo 5. Lenguajes de programacio
un lenguaje simb´ olico como se indica en la figura 5.2. Aunque el paso dado es importante, los lenguajes simb´ olicos consisten s´olo en una representaci´ on m´ as inteligible de las instrucciones de m´aquina. El siguiente paso consisti´ o en incorporar en los lenguajes simb´olicos macroinstrucciones, para representar secuencias de instrucciones de utilizaci´ on frecuente. Estos lenguajes se conocen como ensambladores. Enseguida se comprendi´ o la necesidad de escribir programas que tradujeran textos escritos en ensamblador a textos escritos en lenguaje m´aquina. Estos programas traductores se llaman tambi´en ensambladores.
5.1.2
Lenguajes de alto nivel
A diferencia de los lenguajes orientados a la m´ aquina, los lenguajes de alto nivel se componen de “t´erminos” y “frases” relacionados con el problema en resoluci´ on. As´ı por ejemplo, una ecuaci´ on de segundo grado ax2 + bx + c = 0 se podr´ıa resolver en un lenguaje de alto nivel como se indica en la figura 5.3. Por razones obvias, se dice que los lenguajes de alto nivel est´an orientados al problema. Esta ventaja es doble: por un lado, permiten al programador concentrar su atenci´ on sobre el problema, ignorando los detalles propios de la m´ aquina concreta que lo ha de resolver; por otra parte, como el discurso de los programas de alto nivel es independiente de la m´aquina, son altamente compatibles (transportables) entre m´ aquinas diferentes. En la figura 5.4 se clasifican los lenguajes de programaci´ on, de m´ as evolucionados a m´ as cercanos a la m´aquina. En los u ´ltimos a˜ nos se ha desarrollado una generaci´ on de lenguajes de muy alto nivel, que incorporan diversos mecanismos para aumentar su capacidad expresiva en alg´ un aspecto. En el apartado siguiente introducimos algunos de esos modelos.
5.1. Lenguajes de bajo y alto nivel
... readln (a, b, c); discrim := sqr(b) - 4 * a * c; if discrim >= 0 then begin writeln ((-b+sqrt(discrim))/(2*a)); writeln ((-b-sqrt(discrim))/(2*a)) end else begin real := -b/(2*a); imag := sqrt(-discr)/(2*a); writeln(real, ’+’, imag, ’i’); writeln(real, ’-’, imag, ’i’); end ... Figura 5.3. Fragmento de un programa en un lenguaje de alto nivel
declarativos
lenguajes simb´olicos
lenguajes binarios
de alto nivel
alto y muy alto nivel
ensambladores bajo nivel de m´aquina
Figura 5.4. Distintos tipos de lenguajes de programaci´ on.
123
124
5.1.3
´n Cap´ıtulo 5. Lenguajes de programacio
Paradigmas de programaci´ on
Programaci´ on imperativa—programaci´ on declarativa La forma tradicional de programar recibe el nombre de programaci´ on imperativa, ya que un programa no es m´ as que una secuencia de ´ordenes o instrucciones que deb´ıan ser ejecutados por el computador. Este modelo de computaci´ on ha influido fuertemente en la naturaleza de los lenguajes de programaci´ on; aunque la evoluci´ on de ´estos ha permitido esconder muchas caracter´ısticas de bajo nivel, los lenguajes convencionales todav´ıa presentan un estilo de programaci´ on basado en dotar al computador de procedimientos para resolver problemas, dici´endole c´ omo se resuelven. Este paradigma de programaci´ on obliga al programador a tener siempre presentes los detalles particulares del computador que ejecutar´ a sus programas. Algunos de los lenguajes imperativos m´ as difundidos en la actualidad son el COBOL, BASIC, FORTRAN, Pascal, Modula 2 y C. Una de las opciones para hacer m´as simple el trabajo de programar consiste en separar al programador del modelo computacional subyacente. De este modo se podr´a concentrar en el desarrollo del programa como una especificaci´ on clara y concisa de la respuesta a un problema. Al elegir esta soluci´on se est´a optando por un estilo declarativo de programaci´on, llamado as´ı porque lo que se hace es “declarar” (especificar) el problema que se quiere resolver en lugar de proporcionar la secuencia de acciones que el computador debe ejecutar para hallar la respuesta. En lugar de indicar c´ omo operar, en programaci´ on declarativa se indica qu´e resolver. Por lo tanto, los lenguajes declarativos est´ an m´ as cerca del enunciado que de la resoluci´ on propiamente dicha. Por eso se les considera lenguajes de muy alto nivel. Dentro del paradigma de programaci´ on declarativa se han desarrollado dos enfoques: la programaci´ on funcional y la programaci´ on l´ ogica.
5.1. Lenguajes de bajo y alto nivel
125
ra´ıces(a,b,c) = let discr ≡ sqr(b) - 4 * a * c in if discr ≥ 0 then ((-b+sqrt(discr))/(2*a),(-b-sqrt(discr))/(2*a)) else let (real, imag) ≡ (-b/(2*a), sqrt(-discr)/(2*a)) in ((real,‘+’,imag,‘i’),(real,‘-’,imag,‘i’)) Figura 5.5.
Programaci´ on funcional La programaci´ on en un lenguaje funcional consiste en construir funciones que el computador debe evaluar. La tarea primordial del programador es la construcci´on de una funci´ on que resuelva un problema dado; esta funci´ on puede depender de otras funciones subsidiarias y esta dependencia se expresa en una notaci´ on que obedece los principios matem´aticos elementales. El papel del computador no es otro que el de evaluar las funciones e imprimir los resultados. Esta caracter´ıstica ha permitido que los lenguajes funcionales no dependan de ning´ un modelo particular de arquitectura, en contraste con la mayor´ıa de los lenguajes imperativos. La programaci´ on funcional tiene sus ra´ıces en la l´ogica y en las matem´aticas. En los programas funcionales se hace uso de conceptos y notaciones familiares a toda persona que tenga conocimientos elementales de matem´aticas; de hecho, la derivaci´ on de programas funcionales a partir de su especificaci´ on se suele realizar mediante razonamiento ecuacional (aplicando las ecuaciones que definen las funciones implicadas en el programa). Un programa funcional puede interpretarse, bien como un conjunto de definiciones (declaraciones) de propiedades o bien como un conjunto de reglas de computaci´on. La primera interpretaci´ on la realiza el programador que est´a especificando (declarando) el problema, diciendo qu´e se busca en lugar de c´ omo se encuentra; por el contrario, el computador
126
´n Cap´ıtulo 5. Lenguajes de programacio
entiende el programa como un conjunto de reglas de reescritura que le permitir´ an, finalmente, proporcionar la soluci´ on del problema. Los lenguajes funcionales tienen muchas caracter´ısticas atractivas, entre las que se encuentran: • Los programas funcionales son bastante m´ as cortos y legibles que los imperativos. • Su fuerte base matem´atica hace m´as f´acil razonar sobre la correcci´on de los programas. • El significado de una expresi´ on es su valor, que no cambia durante la ejecuci´on del programa. Uno de los primeros lenguajes funcionales que se desarrollaron fue el LISP, aunque no se considera completamente funcional por tener tambi´en caracter´ısticas no funcionales. Otros ejemplos de lenguajes funcionales desarrollados en la actualidad son el Hope, ML y Miranda. El ejemplo de la figura 5.5 muestra, en el estilo de estos lenguajes, la soluci´ on de la ecuaci´on de segundo grado. Programaci´ on l´ ogica En programaci´ on imperativa, un programa no es otra cosa que el gui´ on de las acciones que el computador debe seguir, y su ejecuci´on consiste en obedecer esas ´ordenes. En programaci´ on l´ ogica, un programa consiste en una serie de sentencias de la l´ogica matem´atica que describen un mundo, y su ejecuci´ on consiste en deducir alg´ un objetivo propuesto. Las sentencias mencionadas pueden ser de dos clases: hechos, similares a los axiomas de la l´ogica, o reglas de deducci´ on, que definen relaciones entre objetos. Las siguientes sentencias por ejemplo establecen una parte del pedigree de un perro:
5.1. Lenguajes de bajo y alto nivel
127
hij(tobi, laika) macho(tobi) hembra(laika) hij(tobi, pipo) macho(pipo) ... y podr´ıan leerse como sigue: “Tobi es hijo/a de Laika”, “Tobi es macho”, etc. Establecen hechos ciertos sobre objetos concretos. Las reglas establecen tambi´en verdades, aunque se refieren a objetos gen´ericos,1 por lo que tienen un car´ acter m´as general: padre(P, H)