Sei sulla pagina 1di 58

Lenguajes de programacin

Abdiel E. Cceres Gonzlez


Instituto Tecnolgico de Monterrey Campus Ciudad de Mxico Verano 2004

Tower of Babel by Gustav Dore 1986 1

Pascal

Aunque ALGOL nunca se volvi un lenguaje muy popular, su inuencia fue enorme sobre los lenguajes imperativos (o sea, estructurados) que le sucedieron. El PL/I fue un intento fallido de IBM por combinar ALGOL, FORTRAN y COBOL en un solo lenguaje de programacin. El resultado fue un autntico desastre, porque este lenguaje tena demasiadas interacciones de funciones, adems de ser enorme y difcil de controlar.

Pascal

Consecuentemente, el PL/I nunca se volvi muy popular y ha sido criticado constantemente por la mayor parte de los diseadores de lenguajes debido a su horrible estructura y su tremenda redundancia. Otro enfoque distinto de diseo fue el denominado lenguajes expandibles, el cual consista en desarrollar un kernel o lenguaje base y un mecanismo que permitiera extenderlo hacia el tipo de aplicacin que se deseara. Haban varios tipos posibles de extensin, tales como la extensin de operadores y las macros sintcticas.

Pascal

En el primer caso, podan denirse nuevos operadores de acuerdo a las necesidades del usuario. En el segundo casi, poda introducirse una nueva sintaxis en el lenguaje. El problema principal con los lenguajes expandibles era su ineciencia, debida al hecho de que las extensiones no se implementaban directamente en el compilador y por lo tanto haba un costo de indireccin asociado a ellas. Otro problema era el diagnstico pobre de los lenguajes expandibles. Esto se deba a que el chequeo de errores lo haca el kernel del lenguaje. Debido a esto, la mayor parte de los diagnsticos se realizaban en trminos de constructores del lenguaje usado por el kernel, el cual resultaba sumamente confuso para el usuario.

Pascal

Aunque los lenguajes expandibles no lograron sobrevivir hasta nuestros das, algunos lenguajes de programacin tales como Ada y Scheme todava incorporan extensiones a los operadores y macros sintcticas como mecanismos alternativos para extender el lenguaje. Niklaus Wirth empez a trabajar en su propia implementacin de ALGOL (llamada Algol-W) en 1968 y para 1970 ya tena un compilador completamente funcional.

Pascal

Las ideas originales de Wirth en torno a posibles extensiones al ALGOL fueron rechazadas por el comit que desarroll este lenguaje. En vez de hacerle caso a Wirth, el comit opt por desarrollar un lenguaje ms grande, ms sutil y excesivamente complejo, al que denominaron ALGOL-68. Sin embargo, Algol-W fue implementado en Stanford y usado durante varios aos para la enseanza.

Pascal

El lenguaje fue renombrado Pascal y fue revisado ligeramente en 1972, volvindose un estndar internacional en 1982.

Pascal

Aunque recientemente ha sido desplazado por C/C++, Pascal fue un lenguaje muy importante en la enseanza de programacin y diseo de compiladores, usndosele por muchos aos en todo el mundo. Las metas principales del diseo de Pascal fueron: El lenguaje deba ser adecuado para ensear programacin en una forma sistemtica. La implementacin del lenguaje deba ser conable y eciente, tanto en tiempo de compilacin como en tiempo de ejecucin. Dicha eciencia estaba especicada de acuerdo al equipo disponible en la poca (nes de los 1960s).

Pascal

Pascal es un lenguaje muy simple y general. Es algo as como un ALGOL sin ningn exceso, ya que todas las cosas barrocas de este lenguaje se removieron de Pascal. Asimismo, cuenta con algunas estructuras de datos adicionales, pero stas tienen como n facilitar y hacer ms eciente el lenguaje. El punto ms fuerte de Pascal es su simplicidad y a ella se atribuye su xito prolongado a lo largo de tantos aos en todo el mundo. Pascal tiene una sintaxis muy similar a la de ALGOL, pero realiza importantes adiciones a los mecanismos de identicacin, datos y estructuras de control. Adems de permitir declarar variables y procedimientos, Pascal introduce declaraciones de constantes y de nuevos tipos de datos.

Pascal

Tambin cuenta con estructuras if-then-else y con ciclos for (en una forma muy simplicada). Asimismo, hay ciclos con la decisin al inicio y al nal y una sentencia case para manejar casos. A continuacin analizaremos algunas de las caractersticas ms importantes de Pascal. Pascal cuenta con un tipo de datos para las enumeraciones. Este mecanismo es de muy alto nivel y muy orientado a las aplicaciones. Las enumeraciones permiten a los programadores expresarse directamente, sin tener que usar variables enteras.

10

Enumeraciones

Ejemplo: type DiaSemana = (Dom, Lun, Mar, Mie, Jue, Vie, Sab); Las enumeraciones son ecientes porque permiten que el compilador optimice espacio de almacenamiento y las operaciones en que se les involucra pueden realizarse rpidamente.

11

Enumeraciones

Puesto que el compilador sabe con anticipacin cul es el nmero total de valores que contendr la enumeracin, puede asignar exactamente la cantidad de bits que se requiera para representarla, en vez de tener que usar el nmero total de bits que requerira normalmente un entero. Por ejemplo, si nuestra enumeracin tendr 7 valores posibles, el compilador puede usar 3 bits para representar cada elemento. Esto contrasta con los 16 32 bits que normalmente requerira el tipo integer para cada elemento de la enumeracin. Ejemplo: Dom 000 Lun 001 Mar 010 Mie 011 Jue 100 Vie 101 Sab 110

12

Enumeraciones

Las enumeraciones son seguras porque el compilador se asegura que los programadores no puedan efectuar operaciones sin sentido. Los nicos operadores permisibles son: :=, succ, pred, =, < >, <, >, <=, >= y operaciones tales como succ(Sab) y pred(Dom) producirn mensajes de error.

13

Denicin de Subrangos

Pascal permite al programador denir subrangos de cualquier tipo de datos discreto (enteros, caracteres y enumeraciones). Ejemplo: var DiaMes : 1..31; Esto signica que DiaMes puede tomar valores en el rango 1 a 31 (inclusive). Si intentamos asignar a esta variable un valor fuera de este rango, obtendremos un mensaje de error. Este es un mecanismo muy seguro (es fcil interceptar errores al usar subrangos) y eciente (podemos usar slo unos cuantos bits para representar un rango grande en vez de usar enteros de longitud ja).

14

Conjuntos

Pascal proporciona la capacidad de manipular pequeos conjuntos nitos usando operaciones estndar de teora de conjuntos. Los conjuntos son un tipo de datos muy til que pueden ser implementados muy ecientemente y proporcionan un nivel muy alto de abstraccin.

15

Conjuntos

La descripcin del tipo conjunto tiene la forma siguiente: set of <tipo ordinal> donde <tipo ordinal> es una enumeracin (incluyendo los tipos char y Boolean), un subrango o el nombre de uno de stos. Podemos declarar conjuntos usando: var S,T : set of 1..10;

16

Conjuntos

Posteriormente, podemos asignar valores a un conjunto usando: S:=[1,2,3,4,6]; T:=[1..4]; Esta segunda asignacin signica que el conjunto contiene los enteros del 1 al 4. Tambin se proporcionan operaciones regulares de conjuntos. Por ejemplo, la interseccin se denota mediante el asterisco (*): T:=S*T; La unin se denota mediante el signo +, la diferencia se indica mediante el signo - y la igualdad mediante el signo =.

17

Conjuntos

La relacin de subconjunto se denota mediante <=. Por ejemplo, si: S:=[1,2,3,5,7]; T:=[1,2,3,5]; entonces T<=S devolver CIERTO (true). Adicionalmente, se proporcionan los operadores relacionales <> (desigualdad) y >=. Aunque no se proporcionan < y >, pueden derivarse muy fcilmente. Por ejemplo, T<S es equivalente a S<=T and S<>T.

18

Conjuntos

El constructor de conjuntos es de muy alto nivel, puesto que permite a los programadores presentar algoritmos en una notacin muy natural. Adems, el constructor es muy eciente porque est implementado usando operaciones sobre vectores de bits. Ejemplo: var S: set of 1..10; S:=[1,2,3,5,7]; En este caso, slo se requieren 10 bits para representar a todo posible elemento de S.

19

Conjuntos

Por ejemplo, para representar al conjunto S antes denido, haramos lo siguiente: S=1 1 1 0 1 0 1 0 0 0 1 2 3 4 5 6 7 8 9 10 Las operaciones de conjuntos tambin se pueden implementar muy ecientemente. Por ejemplo: S:=[1,2,3,5,7]; T:=[1,2,3,4,5,6];

20

Conjuntos

Interseccin: Efectuar un AND lgico de los bits que representan los elementos de los 2 conjuntos: S = 1 T S T = 1 = 1 1 1 1 1 1 1 0 1 0 1 1 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0

S*T

= [1,2,3,5];

21

Conjuntos

Unin: Efectuar un OR lgico de los bits que representan los datos de los 2 conjuntos: S = T = S T = 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 0 1 1 1 0 1 0 0 0 0 0 0 0 0 0

S+T

= [1,2,3,4,5,6,7];

22

Conjuntos

Complemento: Efectuar un NOT lgico de los bits que representan los elementos del conjunto: S = NOT S = 1 0 1 0 1 0 0 1 1 0 0 1 1 0 0 1 0 1 0 1

COMPLEMENTO DE S = [4,6,8,9,10]

23

Conjuntos

Diferencia: A-B=A AND (NOT B). S = T = 1 1 1 1 1 1 0 1 0 0 1 1 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 1 0 1 0

NOT T= S&(!T)=

S-T = [7]

24

Arreglos

Los arreglos en Pascal pueden usar subndices de tres tipos: enteros, enumeraciones o caracteters. Ejemplo: var Dias : array[Lun..Vie] of 0..24; Una de las ventajas principales de usar subrangos en este caso es que anulamos la posibilidad de tener subndices ilegales.

25

Arreglos

De esta manera, estamos dejando la tarea de chequeo para el tiempo de compilacin, en vez de postergarla al tiempo de ejecucin. De hecho, Pascal permite usar cualquier tipo de datos nito como subndice de un arreglo. Pascal permite arreglos de cualquier tipo (enteros, reales, caracteres, enumeraciones, subrangos, registros, apuntadores, etc.).

26

Arreglos

Realmente Pascal no permite arreglos multidimensionales. Sin embargo, debido a que el tipo base de un arreglo puede ser cualquiera, se incluye tambin el caso de otro arreglo. De esa manera, podemos tener arreglos de arreglos (o sea, arreglos de cualquier nmero de dimensiones). Sin embargo, una limitante de los arreglos en Pascal es que son estticos y no semidinmicos como en ALGOL. Esto se debe a una interaccin de funciones: 1) Todos los tipos deben poder determinarse en tiempo de compilacin. 2) Las dimensiones son parte del tipo de un arreglo.

27

Arreglos

Por s solas, ninguna de estas dos decisiones parecen peligrosas y de hecho, tienen mucho sentido si se analizan por separado. Sin embargo, cuando se juntan, tenemos un problema. Dado que la dimensin de un arreglo es parte del tipo y debido a que los tipos deben poderse determinar en tiempo de compilacin, entonces en consecuencia las dimensiones del arreglo deben ser estticas (o sea, conocerse en tiempo de compilacin).

28

Arreglos

Hay otro problema de interaccin de funciones ms serio todava: 1) Las dimensiones son parte del tipo de un arreglo. 2) Pascal usa chequeo fuerte de tipos; por tanto, el tipo de un parmetro pasado a un procedimiento invocado debe coincidir con el del procedimiento invocador. Esto signica que si tenemos un arreglo cuyo subndice est denido como una enumeracin 1..100, y le queremos pasar a otro arreglo del mismo tamao, pero cuyo subndice est denido como una enumeracin 0..99, los 2 arreglos se considerarn de tipos distintos y obtendremos un error.

29

Arreglos

Esto viola el principio de abstraccin, porque tenemos que escribir un procedimiento separado para cada subrango distinto de nuestro programa. El comit que estandariz Pascal resolvi este problema introduciendo el denominado esquema de arreglo conformante para especicar el parmetro de un procedimiento a invocarse. Ejemplo: procedure suma(x:array[linf..lsup:integer] of real):real; De esta manera, cualquier arreglo indizado con enteros puede pasarse al procedimiento suma. Con este esquema, cuando pasamos un arreglo al procedimiento suma, los identicadores linf y lsup se asocian a los lmites inferior y superior del tipo de ndice que tenga x.

30

Arreglos

Aunque esto resuelve el problema del paso de arreglos en Pascal, hace al lenguaje menos regular y le introduce una mayor complejidad.

31

Registros

Una de las estructuras de datos ms importantes de Pascal son los registros. Esta estructura de datos permite agrupar datos de diferente tipo.

32

Registros

La idea de los registros se tom de COBOL, y Anthony Hoare sugiri incorporarlos en los lenguajes orientados a aplicaciones cientcas.

33

Registros

Al igual que un arreglo, los registros tienen componentes. Sin embargo, a diferencia de los arreglos, los registros permiten componentes de tipos diferentes. type persona= record nombre : cadena; edad : 18..90; genero : (masculino, femenino); end; cadena=packed array[1..30] of char;

34

Registros

Puede seleccionarse un componente de un arreglo usando un punto entre el nombre del registro y el nombre del componente. Ejemplo (suponiendo que nuevo es un registro de tipo persona): nuevo.edad = 20; Los registros son estructuras denidoras de entornos, ya que agrupan nombres de campos que no son visibles fuera de la declaracin del registro, a menos que se use el operador punto para abrirlo.

35

Registros

Si necesitamos colocar datos en varios componentes de un registro de forma sucesiva, podemos usar la sentencia with: with nuevo do begin edad:=20; genero:=masculino; end;

36

Registros vs. Arreglos

Tipo de los elementos

Selectores

Arreglo

Homogneos (menos generales)

Dinmicos (Ms generales)

Registro

Heterogneos (ms generales)

Estticos (menos generales)

37

Registros vs. Arreglos

La razn por la que Pascal incluye tanto arreglos como registros es porque son estructuras de datos de naturaleza distinta. Los registros agrupan datos heterogneos, mientras los arreglos slo agrupan datos homogneos. Los arreglos pueden usar subndices cuyo valor se calcule en tiempo de ejecucin. Por ejemplo: A[E] donde E es una expresin cuyo valor se determina en tiempo de ejecucin.

38

Registros vs. Arreglos

Esto es muy til porque permite, por ejemplo, la manipulacin de los elementos de un arreglo (a travs de un ciclo) en tiempo de ejecucin. No puede hacerse lo mismo con los registros. Esto se debe a que los tipos deben ser checados en tiempo de compilacin. De tal forma, no pueden hacerse cosas como: registro.E donde E es una expresin cuyo valor se determina en tiempo de ejecucin.

39

Registros Variantes

Pascal tambin proporciona otro tipo de estructura de datos a la que se denomina registros variantes. Estos registros permiten agrupar diferentes campos de acuerdo al estatus con el que estn asociados. Los registros variantes son una especie de sentencia case dentro de un registro y son muy tiles cuando tenemos ciertos atributos que sabemos de antemano que slo usaremos en ciertas situaciones. Los registros variantes ahorran memoria, porque como slo una de las estructuras denidas dentro de ellos puede usarse a la vez, el compilador slo necesita reservar memoria para la mayor de ellas (en vez de tener que hacerlo para todos los componentes del registro).

40

Registros Variantes

Esta propiedad de comparticin de espacio en memoria es similar a la de los bloques disjuntos en ALGOL. De hecho, tambin en el caso de los registros variantes se permite el anidamiento. Por tanto, los registros variantes son muy ecientes y seguros, porque slo permiten al programador realizar operacions qe tengan algn signicado dentro del contexto dado y que sean permisibles dentro del registro. Sin embargo, el problema con esta estructura de datos es que no requiere ser inicializada. Esto signica que podramos tener cualquier valor dentro de un registro variante despus de modicar el valor de un campo identicador.

41

Registros Variantes

Este problema se produce porque Pascal (al igual que la mayora de los lenguajes estructurados) no requiere que se inicialicen las variables al entrar a su entorno. El acceso a variables no inicializadas puede dar lugar a que se usen valores que fueron dejados previamente en el bloque y que compartan la misma zona de memoria. En el caso de los registros variantes, este valor puede incluso ser de un tipo diferente al esperado. De hecho, algunos programadores aprovechan este subterfugio de Pascal para violar su slido sistema de tipos y realizar algn tipo de programacin de sistemas. La raz del problema es que los registros variantes permiten una forma de aliasing, ya que los campos de las diferentes variantes son todos alias de las mismas posiciones de memoria.

42

Apuntadores

FORTRAN y ALGOL no proporcionaban apuntadores porque estaban orientados a aplicaciones cientcas y las listas ligadas se usaban ms frecuentemente en la programacin de sistemas. Un apuntador nos permite accesar una posicin de memoria directamente. Los apuntadores son muy tiles para implementar listas ligadas, rboles, grafos, etc. Niklaus Wirth decidi, sin embargo, incorporar apuntadores en Pascal, con lo que hizo al lenguaje ms poderoso. Adems, hizo que este mecanismo fuera muy seguro al requerir que los apuntadores tuviesen un tipo asociado a ellos.

43

Apuntadores

Ejemplo: var p : real; Esto nos permite mantener las ventajas de un sistema fuerte de tipos al usar los apuntadores. Adicionalmente, esto elimina la posibilidad de que se produzcan muchos de los errores que suelen caracterizar a los programas en C o ensamblador. El tipo base de un apuntador puede ser cualquiera, incluyendo registros y arreglos.

44

Equivalencia Estructural vs. Equivalencia de Nombres

El Reporte Revisado de Pascal dice que puede asignarse una variable a una expresin si ambas tienen un tipo idntico. Desgraciadamente, el reporte no especica lo que signica que dos tipos sean idnticos, y pueden drsele varias interpretaciones a este enunciado. Esto dio origen a una famosa controversia en computacin, producindose en consecuencia dos interpretaciones diferentes de la equivalencia de tipos: Equivalencia Estructural Equivalencia de Nombres

45

Equivalencia Estructural vs. Equivalencia de Nombres

Equivalencia Estructural: Dos tipos se consideran equivalentes si tienen la misma estructura. Ejemplo: type persona = record id: integer; peso: real end; auto = record id: integer; peso: real end;

varx : persona; y : auto;

46

Equivalencia Estructural vs. Equivalencia de Nombres

Bajo equivalencia estructural, x:=y es una sentencia vlida, ya que los tipos de las 2 variables son exactamente los mismos (palabra por palabra). Esto a pesar de que ambas variables fueron declaradas por separado. De hecho, podra intuirse que el programador pretenda que estas dos variables tuviesen tipos diferentes y que fue una mera coincidencia que los nombres de sus tipos fueran iguales. Bajo este esquema, ambos tipos se consideran idnticos.

47

Equivalencia Estructural vs. Equivalencia de Nombres

Equivalencia de Nombres: Dos objetos tienen el mismo tipo si los nombres de sus tipos son los mismos. Dado el ejemplo anterior, x:=y es ilegal porque el tipo de x es persona y el tipo de y es auto. Ejemplo: var x : record id: integer; peso: real end; y : record id: integer; peso: real end;

48

Equivalencia Estructural vs. Equivalencia de Nombres

Bajo equivalencia de nombres pura, x y y son diferentes, porque el compilador asignar diferentes identicadores a cada una de estas declaraciones. Por lo tanto, los nombres de sus tipos no sern los mismos. La equivalencia de nombre tiene tambin algunos problemas adicionales. Por ejemplo: type edad = 0 . . 150; var n : integer; a : edad; Es legal la asignacin n:=a?

49

Equivalencia Estructural vs. Equivalencia de Nombres

Bajo equivalencia de nombres pura, la respuesta es no, puesto que n y a tienen tipos cuyos nombres son diferentes. Sin embargo, el Reporte Revisado de Pascal explcitamente permite esta asignacin, puesto que indica que dos objetos se consideran del mismo tipo si uno es un subrango del tipo del otro. Esta no es una manera muy elegante de resolver el problema, porque se introduce una excepcin al lenguaje que habr de recordarse a la hora de programar.

50

Equivalencia Estructural vs. Equivalencia de Nombres

En Algol-68, que se adhiere estrictamente a la equivalencia estructural, los 2 tipos de registros siguientes son equivalentes: mode t1 = struct(int value; ref mode t1 link); mode t2 = struct(int value; ref mode t2 link); Donde mode signica tipo y ref introduce una declaracin de un apuntador.

51

Equivalencia Estructural vs. Equivalencia de Nombres

Peor an, estas declaraciones son tambin equivalentes a: mode t3=struct(int value; ref struct(int value; ref mode t3 link)); Por lo tanto, cualquier segmento de cdigo que opere sobre un objeto de tipo t1, operar tambin sobre un objeto de tipo t3 y viceversa.

52

Equivalencia Estructural vs. Equivalencia de Nombres

Aunque la equivalencia estructural es intuitivamente muy atractiva, depara ciertas sorpresas a los programadores. Adicionalmente, es tambin difcil de implementar. En Ada, que se adhiere estrictamente a la equivalencia de nombres, los dos arreglos siguientes son diferentes: IA : array(Integer range 1..10) of Integer; JA : array(Integer range 1..10) of Integer;

53

Equivalencia Estructural vs. Equivalencia de Nombres

Estos dos arreglos son diferentes porque los nombres annimos (los que les da el compilador) de sus tipos son diferentes. En C se usa equivalencia de nombres para los registros y las uniones y se usa equivalencia estructural para lo dems. Cul de los dos enfoques es mejor? Ha habido un largo debate en torno a este tema, aunque el consenso general parece ser que la equivalencia de nombres es mejor.

54

Equivalencia Estructural vs. Equivalencia de Nombres

Las razones principales por las que suele preferirse la equivalencia de nombres son: 1) La equivalencia de nombres suele ser ms segura, puesto que es menos restrictiva. Se presume que si un programador declara dos veces el mismo tipo es porque tiene una razn para hacerlo. Por lo tanto, considerar estos tipos como diferentes protege la seguridad del programa (previene al programador de hacer algo sin sentido). 2) La equivalencia de nombres es ms fcil de implementar. El compilador slo tiene que comparar las cadenas de caracteres que representan los nombres de los tipos.

55

Equivalencia Estructural vs. Equivalencia de Nombres


Para implementar la equivalencia estructural, es necesario escribir una funcin recursiva que compare las estructuras de datos que representan los tipos de los dos objetos bajo consideracin. Esto tambin suele impactar la eciencia del compilador (lo hace ms lento). Pascal proporciona seis mecanismos de asociacin de nombres (o sea, mtodos para declarar objetos en el lenguaje): 1) Asociaciones constantes 2) Asociaciones de tipos 3) Asociaciones de variables 4) Asociaciones de procedimientos y funciones. 5) Asociaciones de enumeraciones implcitas. 6) Asociaciones de etiquetas.

56

Mecanismos de Asociacin de Nombres

Pascal permite la declaracin de constantes de tipos discretos (enteros, enumeraciones y caracteres), usando la palabra reservada const: const <nombre> = <constante>; El uso de constantes en un programa sigue el Principio de Abstraccin, ya que permite a un programador hacer cambios ms fcilmente en el cdigo.

57

Mecanismos de Asociacin de Nombres

Por ejemplo, al declarar constante la dimensin de un arreglo, este valor podra usarse tambin para establecer lmites de un ciclo. De requerirse un cambio, slo deber modicarse el valor de la constante, en vez de tener que reemplazar todas las ocurrencias de dicho valor en el cdigo. Una de las limitaciones de las declaraciones de constantes es que Pascal no permite el uso de expresiones en ellas. Asimismo, Pascal no permite usar expresiones en las declaraciones de variables ni de tipos. Versiones ms recientes de Pascal y otros lenguajes de programacin han tendido a eliminar esta restriccin.

58

Potrebbero piacerti anche