02 lenguajes de_programacion

28
Diseño de compiladores Lenguajes de Programación

Transcript of 02 lenguajes de_programacion

Diseño de compiladores

Lenguajes de Programación

Aspectos de los LP

• Antes de comenzar con la construcción de un compilador, debemos comprender los conceptos basicos del lenguaje de programación con el que queremos trabajar

• No es el propósito cubrir todos los aspectos de todos los lenguajes de programación

Estático vs. Dinámico

• Uno de los aspectos mas importantes a definir cuando construimos un compilador, es que decisiones puede tomar el compilador sobre el programa

Estático vs. Dinámico

• Si el lenguaje usa una política que permite que el compilador decida sobre un asunto, entonces decimos que el compilador utiliza una política estática, o que el asunto puede ser decidido en tiempo de compilación

• Por el contrario, una política que solo permite decidir cuando ejecutamos, se define como dinámica, o que requiere una decisión en runtime

Scopes (Ámbito)

• Otro punto a considerar, es el scope de las declaraciones

• El scope de una declaración de X, es la región del programa, en la que el uso de X, hacen referencia a esta declaración

• Un lenguaje usa scope estático o léxico, si mirando el programa podemos determinar el scope de un símbolo X

Scopes (Ámbito)

• Por el contrario, un lenguaje utiliza scope dinámico, si con la ejecución del programa, el uso de la variable X puede hacer referencia a diferentes declaraciones de X

• La mayoría de los lenguajes utilizan scope estático o léxico

Environments vs. States

• Otro aspecto importante, es si los cambios que ocurren al ejecutar el programa, afectan los elementos de datos, o la interpretación de los nombres usados para acceder a esos datos

• Por ejemplo, x = y + 1

• Cambia el valor denotado por x

• Sin embargo, un atributo “nombre” dentro de una clase, cambia para cada instancia de la clase

Environments vs. States

Nombres

Variables (Direcciones)

Valores

Environment

State

Environments vs. States

• Environment

– Es una función que mapea nombres en direcciones de memoria

• State

– Es una función que mapea direcciones de memoria en valores

Environments vs. States

• Por ejemplo…dos usos del nombre “i”

int x;

...

void f(...) {

int i;

...

i = 3;

...

}

...

x = i + 1

Scope estático y bloques

• Los lenguajes tipo C utilizan scope estatico

• La estructura del programa, determina el scope de los símbolos

• Lenguajes posteriores como C#, Java y C++ agregaron el concepto de modificador de acceso

– private, public, protected

Scope estático y bloques

• La mayoría de estos lenguajes utiliza una construcción denominada bloque para afectar el scope de los símbolos

• Un bloque es una agrupación de sentencias

• C utiliza { … } para definir un bloque

• Otros lenguajes utilizan begin … end

Scope en C

• Un programa en C consiste en una secuencia de declaraciones top-level de variables y funciones

• Las funciones pueden tener declaraciones de variables. Estas incluyen variables locales y parámetros

– El scope de estas declaraciones están restringidos a la función en la que están contenidos

Scope en C

• El scope de una declaración top-level de un nombre X, consiste en todo el programa, salvo aquellas funciones en donde el nombre X también haya sido declarado

int x;

...

void f(...) {

char x;

...

x = ‘3’;

...

}

...

x = i + 1

Bloques

• Es un tipo de sentencia, puede aparecer en lugar de cualquier tipo de sentencia del programa

• Esta formada por una secuencia de declaraciones seguida de una secuencia de sentencias

• El anidamiento de bloques, es lo que se conoce como estructura de bloques

Bloques

• Decimos que una declaracion D pertence a un bloque B, si B es el bloque mas cercano que contiene a D

• O sea, D esta dentro de B, pero no dentro de un bloque B’ que se encuentre en B

• Esto nos permite definir reglas de scope para cuando trabajamos con bloques

Bloques

• Decimos que una declaración D pertenece a un bloque B, si B es el bloque mas cercano que contiene a D

• O sea, D esta dentro de B, pero no dentro de un bloque B’ que se encuentre en B

• Esto nos permite definir reglas de scope para cuando trabajamos con bloques

Bloques

• Si una declaracion D de un nombre X, pertenece a un bloque B, entonces el scope de D, es el bloque B, incluyendo cualquier nivel de anidamiento, pero excluyendo los bloques B’ en los que X sea redefinida

Control de acceso explicito

• En los lenguajes orientados a objetos, las clases introducen una nueva forma de scope para sus miembros

• En una clase C, el scope de un miembro X, es la clase C, junto con cualquier clase derivada, excepto si esta clase derivada redefine el miembro X – Los modificadores public, private y protected

afectan esto

Scope dinámico

• Una técnica de scope es dinámica, si esta basada en factores que solo pueden ser determinados al ejecutar el programa

• Con scope dinámico, el uso de un nombre X, se refiere a la declaración de X, en la función mas recientemente llamada con esa declaración

Scope dinámico

int x = 2;

void b() (

int x = 1;

printf (”%d\n” , x); // Imprime 1

}

void c() { printf(“%d\n” , x); // Imprime 1

void main() { b(); c(); }

main() b() c()

Pasaje de parámetros

• Lo que nos interesa, es como los parámetros actuales (los que usamos en la invocación a un procedimientos), son asociados con los parámetros formales (los que están en la declaración del procedimiento)

• Tenemos tres formas de pasar parametros

– Call by value, Call by reference, Call by name

Call by value

• El parámetro actual es evaluado (si es una expresión), y su valor es copiado en el parámetro formal

• Es el método usado en C, Java, C# y el mas común en C++

• Los parámetros actuales no se ven afectados por los cambios realizados en el procedimiento

• Podemos pasar por valor, la dirección de memoria de una variable

Call by reference

• En este caso, se pasa la dirección de los parámetros actuales, colocando la misma en los parámetros formales

• El acceso a través de los parámetros formales, se hace siguiendo esta dirección

– Parámetros “ref“ en C++

• Los cambios en los parámetros formales, afectan los parámetros actuales

Call by name

• Este mecanismo ya no es usado hoy

• Funciona como una expansión de una macro en el procedimiento

• Cada parámetro formal, es reemplazado literalmente por el parámetro actual

• En el caso de pasar expresiones como parámetro, esto genera comportamientos poco intuitivos

Aliasing

• Esto se da cuando tenemos pasaje de parámetros por referencia (o por valor, pasando la misma dirección 2 veces)

• Dos parámetros formales diferentes, pueden apuntar al mismo parámetro actual

• Esto genera una situación de alias entre ambos parámetros formales