Download Herramientas desarrolladas con la teoría de la programación de

Document related concepts

Haxe wikipedia , lookup

Ocaml wikipedia , lookup

Lisp wikipedia , lookup

Rust (lenguaje de programación) wikipedia , lookup

Programación funcional wikipedia , lookup

Transcript
Unidad I – Segunda Parte / Programación de Sistemas / Ing. Leonardo Ramírez
Herramientas desarrolladas con la teoría de la programación de sistemas.
Las herramientas de programación, son aquellas que permiten realizar aplicativos, programas, rutinas, utilitarios y
sistemas; para que la parte física del computador u ordenador, funcione y pueda producir resultados.
Hoy en día existen múltiples herramientas de programación en el mercado, tanto para analistas expertos como para
analistas inexpertos.
Las herramientas de programación más comunes del mercado, cuentan con programas de depuración o “debugger”,
que son utilitarios que nos permiten detectar los posibles errores en tiempo de ejecución o corrida de rutinas y
programas.
Muchas herramientas de software que manipulan programas fuente realizan primero algún tipo de análisis a la
estructura del código.
Algunos ejemplos de tales herramientas son:
Editores de estructuras.
Un editor de estructuras toma como entrada una secuencia de órdenes para construir un programa fuente. El editor
de estructuras no sólo realiza las funciones de creación y modificación de textos de un editor de textos ordinario,
sino que también analiza el texto del programa, imponiendo al programa fuente una estructura jerárquica
apropiada. De esa manera, el editor de estructuras puede realizar tareas adicionales útiles para la preparación de
programas. Por ejemplo, puede comprobar si la entrada está formada correctamente, puede proporcionar palabras
clave de manera automática (por ejemplo, cuando el usuario escribe while, el editor proporciona el correspondiente
do y le recuerda al usuario que entre las dos palabras debe ir un condicional) y puede saltar desde un begin o un
paréntesis izquierdo hasta su correspondiente end o paréntesis derecho. Además, la salida de tal editor suele ser
similar a la salida de la fase de análisis de un compilador.
Impresoras estéticas.
Una impresora estética analiza un programa y lo imprime de forma que la estructura del programa resulte
claramente visible. Por ejemplo, los comentarios pueden aparecer con un tipo de letra especial, y las proposiciones
pueden aparecer con una indentación proporcional a la profundidad de su anidamiento en la organización jerárquica
de las proposiciones.
Verificadores estáticos.
Un verificador estático lee un programa, lo analiza e intenta descubrir errores potenciales sin ejecutar el programa.
La parte de análisis a menudo es similar a la que se encuentra en los compiladores de optimización. Así, un
verificador estático puede detectar si hay partes de un programa que nunca se podrán ejecutar o si cierta variable se
usa antes de ser definida. Además, puede detectar errores de lógica, como intentar utilizar una variable real como
apuntador, empleando las técnicas de verificación de tipos.
Intérpretes.
En lugar de producir un programa objeto como resultado de una traducción, un intérprete realiza las operaciones
que implica el programa fuente. Muchas veces los intérpretes se usan para ejecutar lenguajes de órdenes, pues cada
operador que se ejecuta en un lenguaje de órdenes suele ser una invocación de una rutina compleja, como un editor
o un compilador. Del mismo modo algunos lenguajes de “muy alto nivel”, normalmente son interpretados, porque
hay muchas cosas sobre los datos, como el tamaño y la forma de las matrices, que no se pueden deducir en el
momento de la compilación.
Compiladores.
Tradicionalmente, se concibe un compilador como un programa que traduce un programa fuente, como FORTRAN,
al lenguaje ensamblador o de máquina de algún computador. Sin embargo, hay lugares, al parecer, no relacionados
donde la tecnología de los compiladores se usa con regularidad.
Formadores de textos.
Un formador de textos toma como entrada una cadena de caracteres, la mayor parte de la cual es texto para
componer, pero alguna incluye órdenes para indicar párrafos, figuras o estructuras matemáticas, como subíndices o
superíndices.
Unidad I – Segunda Parte / Programación de Sistemas / Ing. Leonardo Ramírez
Compiladores de circuitos de silicio.
Un compilador de circuitos de silicio tiene un lenguaje fuente similar o idéntico a un lenguaje de programación
convencional. Sin embargo las variables del lenguaje no representan localidades de memoria, sino señales lógicas (0
o 1) o grupos de señales en un circuito de conmutación. La salida es el diseño de un circuito en un lenguaje
apropiado.
Intérpretes de consultas.
Un intérprete de consultas traduce un predicado que contiene operadores relacionales y boléanos a órdenes para
buscar en una base de datos los registros que satisfagan ese predicado.
Lenguaje.
Se llama lenguaje a cualquier tipo de código semiótico estructurado, para el que existe un contexto de uso y ciertos
principios combinatorios formales. Existen muchos contextos tanto naturales como artificiales donde aparecen
lenguajes.
El lenguaje humano se basa en la capacidad de los seres humanos para comunicarse mediante signos.
Principalmente lo hacemos utilizando el signo lingüístico. Aún así, hay diversos tipos de lenguaje.
El lenguaje animal se basa en el uso de señales sonoras, visuales y olfativas a modo de signos para referirse a un
referente o un significado diferente de dichas señales.
Dentro del lenguaje animal están los gritos de alarma, el lenguaje de las abejas, etc.
Los lenguajes formales son construcciones artificiales humanas, que se usan en matemática y otras disciplinas
formales, incluyendo lenguajes de programación. Estas construcciones tienen estructuras internas que comparten
con el lenguaje humano natural, por lo que pueden ser en parte analizados con los mismos conceptos que éste.
Ya sea que se trate de un distrito escolar, un banco, un sistema de transporte o una planta manufacturera, la
comunicación eficaz es esencial.
¿Qué es comunicación?
La comunicación se puede definir como la transferencia de información y entendimiento entre personas por medio
de símbolos con significados.
La comunicación en cualquier circunstancia de nuestras vidas, es de vital importancia, para poder expresar nuestros
objetivos, necesidades, emociones, etc., de la misma manera se vuelve imperiosa dentro de las empresas, por lo que
se pueden mencionar algunos beneficios en los cuales ayuda:
· Establecer y difundir los propósitos y metas de la empresa.
· Desarrollar planes para lograr dichos propósitos.
· Organizar los recursos humanos en forma efectiva.
· Seleccionar, desarrollar y evaluar los miembros de dicha empresa.
· Originar un clima de amplia participación.
· Controlar el desempeño de los miembros.
· Influir en la motivación de nuestros trabajadores.
El proceso de la comunicación.
Para llevar a cabo una comunicación eficaz, es necesario que en el flujo de la transmisión de ideas, intervengan
varios elementos, los que se describen a continuación:
1. Emisor (codificador).
Fuente de información e iniciador del proceso de comunicación. Es su responsabilidad elegir el tipo de mensaje y
canal más eficaces, tras de lo cual codifica el mensaje. En una empresa será la persona que tiene una información,
necesidades o deseos y la intención de comunicarlos a una o más personas.
La Codificación consiste en la traducción de información a una serie de símbolos para la comunicación. Esta es
necesaria porque la información únicamente puede transmitirse de una persona a otra por medio de
representaciones o símbolos.
2. Receptor (decodificador).
Es el individuo que recibe, por medio de sus sentidos, el mensaje del transmisor.
Unidad I – Segunda Parte / Programación de Sistemas / Ing. Leonardo Ramírez
La decodificación es la interpretación y traducción de un mensaje para que la información tenga sentido. Uno de los
principales requisitos que debe cubrir el receptor es la capacidad de escuchar. Escuchar es el acto de prestar
atención a un mensaje, no únicamente oírlo.
Lineamientos para la escucha eficaz.
3. Mensaje.
Es la información codificada que el transmisor envía al recepto. El mensaje puede darse en cualquier forma
susceptible de ser captada y entendida por uno o más de los sentidos del receptor.
4. Canales.
Es el medio de comunicación entre el transmisor y el receptor, algo así como el aire es para las palabras y el papel
para las letras.
5. Retroalimentación.
Es la respuesta del receptor al mensaje del emisor. Es la mejor manera de comprobar que el mensaje se recibió y
comprendió.
6. Percepción.
Es el significado atribuido a un mensaje por un emisor o receptor. Las percepciones se ven influidas por lo que ven
los individuos, por la manera en que organizan esos elementos en su memoria y por los significados que les
atribuyen.
Diagrama del Proceso de la Comunicación.
Unidad I – Segunda Parte / Programación de Sistemas / Ing. Leonardo Ramírez
Barreras en la Comunicación.
Son las condiciones o factores que interfieren en la transmisión efectiva de un mensaje, y entre ellas se encuentran:
Barreras Interpersonales.
· La interpretación que realiza el receptor del mensaje.
· Defectos fisiológicos del emisor o receptor.
· Los sentimientos y emociones del emisor o receptor.
· Las condiciones medio-ambientales en que se da el mensaje.
· El uso de la semántica, tales como diferencias de lenguaje, palabras no adecuadas, información insuficiente, etc.
Barreras Organizacionales.
Cuando una empresa crece, su estructura orgánica se amplía mucho, originando problemas en la comunicación, con
lo que se generan situaciones donde se agrega, se modifica, se elimina o se cambia totalmente un mensaje, y más si
el mensaje ha sido transmitido en forma oral.
Otra barrera se traduce en la autoridad administrativa, donde se debe recordar que la autoridad es una
característica de toda empresa, por lo que, esa supervisión genera una barrera, y por último, la especialización es
otra barrera que afecta la eficacia de la comunicación.
Lenguajes de Programación.
Un lenguaje de programación está formado por un conjunto de símbolos básicos (alfabeto) y un conjunto de reglas
que especifican como manipularlos. También debe darle significado a las cadenas formadas al manipular los
símbolos básicos.
Los lenguajes de programación pueden clasificarse de acuerdo a su semejanza con el lenguajes maquina o a su
semejanza con el lenguaje humano (generalmente inglés).
Los lenguajes que tiene mayor semejanza con el lenguaje humano se les llama lenguajes de alto nivel, mientras que
los lenguajes más parecidos al lenguaje de maquina son conocidos como de bajo nivel.
Entre los lenguajes de bajo nivel se encuentra el lenguajes ensamblador. Algunos ejemplos de lenguajes de alto nivel
son:
 Algol, Basic, C, Cobol, Fortran, Modula 2, Pascal, Prolog.
Traductor y su estructura.
Un traductor es un programa que recibe como entrada código escrito en un cierto lenguaje y produce como salida
código en otro lenguaje. Generalmente el lenguaje de entrada es de más alto nivel que el de salida. Ejemplos de
traductores son los ensambladores y los compiladores.
En un sentido orientado hacia la computación, un traductor, de manera general, es un software que toma como
entrada un programa escrito en un código llamado fuente y genera como salida otro programa en un código llamado
objeto.
Un ensamblador, es un programa que traduce de un lenguaje ensamblador a lenguaje máquina, mientras que un
compilador es un programa que traduce de un lenguaje de alto nivel a un lenguaje de bajo nivel o a lenguaje
máquina.
Si el código fuente está en un lenguaje abstracto o de alto nivel y si el objetivo es un lenguaje de ensamble de bajo
nivel o de máquina, el traductor que usamos es un compilador.
Algunos ejemplos de traductores son los compiladores (toma como entrada código en alto nivel y genera como
salida código en bajo nivel), los intérpretes (toma como entrada código en alto nivel y genera como salida un código
intermedio), los preprocesadores (toma como entrada código en alto nivel y genera como salida código en alto nivel)
y el ensamblador (toma como entrada código en ensamblador y genera como salida código en bajo nivel).
Su estructura podría ser expresada de la siguiente manera:
código fuente → traductor → código objeto
Intérpretes o Traductores.
Definición. Un intérprete es un programa que ejecuta un programa escrito en un determinado lenguaje examinando
y ejecutando cada sentencia del programa una a una, por separado y sin realizar un proceso de compilación previo.
Al contrario de lo que se podría pensar el intérprete NO traduce la sentencia a código máquina antes de ejecutarla.
En su lugar, identifica el tipo de sentencia y la ejecuta directamente. El código para ejecutar la sentencia está
contenido dentro del intérprete que contendrá rutinas para: evaluar una expresión, almacenar información en
Unidad I – Segunda Parte / Programación de Sistemas / Ing. Leonardo Ramírez
memoria, recuperar datos de memoria, etc. El intérprete contendrá el número de rutinas necesarias para poder
ejecutar cualquier sentencia del lenguaje que está interpretando.
Ejemplo:
C=A+B
1. El intérprete lee la sentencia y determina que es una asignación.
2. Llamará a una de sus rutinas para evaluar la expresión a la derecha de la asignación.
3. Esta rutina toma los símbolos A y B, determina donde están almacenados, obtiene sus valores actuales y los suma.
4. El intérprete toma el valor calculado y lo almacena en la dirección de memoria a la que hace referencia el símbolo
C. Al igual que un compilador para llevar a cabo su tarea el intérprete usará un analizador léxico-gráfico y guardará la
información necesaria para la traducción en una tabla de símbolos.
Interpretar una sentencia es relativamente complejo, al tener que ser escaneada y analizada, los símbolos tienen
que ser buscados, hay que llevar a cabo lo indicado por la sentencia, etc. Esto significa que el número de
instrucciones máquinas a ejecutar para interpretar una sentencia puede ser mucho mayor que el código generado
por un compilador. Además, cada sentencia tendrá que ser interpretada cada vez que aparezca, por lo que una
sentencia en un bucle sería interpretada varias veces.
Además de elegir entre compilar o interpretar un programa, otra opción es combinar ambos procesos de traducción.
En este caso, se realiza una compilación “parcial” a un código intermedio que es seguida de un proceso de
interpretación. Uno de los lenguajes más utilizados hoy en día, sobre todo para el desarrollo de aplicaciones para la
Web, que sigue esta propuesta es el lenguaje Java.
En el lenguaje Java el código primero se compila con el compilador de Java javac. Este compilador genera un código
virtual llamado Byte Code. Este código es luego interpretado por una Máquina Virtual de Java (o JVM de Java Virtual
Machine) que debe estar instalada y ejecutándose en la máquina en la que se desee ejecutar el código compilado
con javac.
Comparación entre compiladores e intérpretes
Históricamente, debido a la escasez de memoria de los primeros ordenadores, se puso de moda el uso de intérpretes
frente a los compiladores, pues el programa fuente sin traducir y el intérprete juntos requerían una cantidad de
memoria menor que la del compilador. Por ello, los primeros ordenadores personales (Spectrum, Commodore VIC20, PC XT de IBM, etc.) iban siempre acompañados de un intérprete de BASIC. La mejor información sobre los errores
por parte del compilador así como una mayor velocidad de ejecución del código resultante hizo que poco a poco se
impusieran los compiladores. Hoy en día, y con el problema de la memoria prácticamente resuelto, se puede hablar
de un gran predominio de los compiladores frente a los intérpretes, aunque intérpretes como los incluidos en los
navegadores de Internet para Java son la gran excepción.
Algunas de las ventajas de compilar frente a interpretar son:
• Se compila una vez; se ejecuta muchas veces.
• La ejecución del programa objeto es mucho más rápida que si se interpreta el programa fuente.
• El compilador tiene una visión global del programa, por lo que la información de mensajes de error es más
detallada.
Por otro lado, algunas de las ventajas de interpretar frente a compilar son:
• Un intérprete necesita menos memoria que un compilador.
• Permiten una mayor interactividad con el código en tiempo de desarrollo.
• En algunos lenguajes (Smalltalk, Prolog, LISP, Java) está permitido y es frecuente añadir código según se ejecuta
otro código, y esta característica solamente es posible implementarla en un intérprete.
Estructura de un Compilador.
Cualquier compilador debe realizar dos tareas principales: análisis del programa a compilar y síntesis de un
programa en lenguaje maquina que, cuando se ejecute, realizara correctamente las actividades descritas en el
programa fuente.
Para el estudio de un compilador, es necesario dividir su trabajo en fases. Cada fase representa una transformación
al código fuente para obtener el código objeto. La siguiente figura representa los componentes en que se divide un
compilador. Las tres primeras fases realizan la tarea de análisis, y las demás la síntesis.
En cada una de las fases se utiliza un administrador de la tabla de símbolos y un manejador de errores.
Unidad I – Segunda Parte / Programación de Sistemas / Ing. Leonardo Ramírez
Análisis Léxico.
En la fase de análisis léxico se leen los caracteres del programa fuente y se agrupan en cadenas que representan los
componentes léxicos. Cada componente léxico es una secuencia lógicamente coherente de caracteres relativa a un
identificador, una palabra reservada, un operador o un carácter de puntuación.
A la secuencia de caracteres que representa un componente léxico se le llama lexema (o con su nombre en inglés
token). En el caso de los identificadores creados por el programador no solo se genera un componente léxico, sino
que se genera otro lexema en la tabla de símbolos.
Análisis Sintáctico.
En esta fase, los componentes léxicos se agrupan en frases gramaticales que el compilador utiliza para sintetizar la
salida.
Análisis Semántico.
La fase de análisis semántico se intenta detectar instrucciones que tengan la estructura sintáctica correcta, pero que
no tengan significado para la operación implicada.
Generación de código Intermedio.
Algunos compiladores generan una representación intermedia explícita del programa fuente, una vez que se han
realizado las fases de análisis. Se puede considerar esta operación intermedia como un subprograma para una
máquina abstracta. Esta representación intermedia debe tener dos propiedades importantes: debe ser fácil de
producir y fácil de traducir al programa objeto.
Optimización de Código.
En esta fase se trata de mejorar el código intermedio, de modo que resulte un código de máquina más rápido de
ejecutar.
Generación de Código.
Esta constituye la fase final de un compilador. En ella se genera el código objeto que por lo general consiste en
código en lenguaje máquina (código relocalizable) o código en lenguaje ensamblador.
Administrador de la tabla de símbolos.
Una tabla de símbolos es una estructura de datos que contiene un registro por cada identificador. El registro incluye
los campos para los atributos del identificador.
El administrador de la tabla de símbolos se encarga de manejar los accesos a la tabla de símbolos, en cada una de las
etapas de compilación de un programa.
Manejador de errores.
En cada fase del proceso de compilación es posibles encontrar errores. Es conveniente que el tratamiento de los
errores se haga de manera centralizada a través de un manejador de errores. De esta forma podrán controlarse más
eficientemente los errores encontrados en cada una de las fases de la compilación de un programa.
Diseño de lenguajes.
El lenguaje de programación puede definirse al describir
1. Lo que parecen sus programas (la sintaxis del lenguaje).
2. Lo que significan sus programas (la semántica del lenguaje).
La sintaxis del lenguaje se presenta ampliamente con una notación denominada gramática libre de contexto o BNF.
(Backus-Naur Form).
La semántica del lenguaje es más difícil de expresar que la sintaxis y generalmente se decide por especificarla usando
descripciones informales y ejemplos.
Ambas situaciones deben ser consideradas por quien diseña un nuevo lenguaje para satisfacer las necesidades de los
usuarios potenciales. Por ejemplo, alguien puede hacer el siguiente requerimiento:
Diseñar un lenguaje para proporcionar órdenes a un robot para que éste se desplace.
Aunque no se especifica qué tipo de órdenes se darán, el diseñador deberá responder a dos preguntas:
Unidad I – Segunda Parte / Programación de Sistemas / Ing. Leonardo Ramírez
1. ¿Cómo expresar lo que queremos que realice la máquina?
2. ¿Cómo debe entender la máquina las órdenes que expresamos?
Puede ser que el tipo de órdenes que se darán sean del tipo: inicio, norte, sur, este, oeste.
De manera que cuando se dé al programa, inicio norte norte este este sur el robot tenga el siguiente
comportamiento:
Si el robot no fuese real sino que tuviera que simularse, la semántica de cada orden sería determinada por modificar
las coordenadas de la posición del robot a través de asociar acciones a las reglas gramaticales, como a continuación
se indican:
Producción regla semántica.
secuencia inicio
secuencia.x:=0
secuencia.y:=0
secuencia secuencia instrucción
secuencia.x:=secuencia1.x+instrucción.dx
secuencia.y:=secuencia1.y + instrucción.dy
secuencia este
instrucción.dx:=1
instrucción.dy:=0
secuencia norte
instrucción.dx:= 0
instrucción.dy:=1
secuencia oeste
instrucción.dx:=-1
instrucción.dy:=0
secuencia sur
instrucción.dx:=0
instrucción.dy:=1
Unidad I – Segunda Parte / Programación de Sistemas / Ing. Leonardo Ramírez
Generación de código.
En programación, la generación de código es una de las fases mediante el cual un compilador convierte un programa
sintácticamente correcto en una serie de instrucciones a ser interpretadas por una máquina. La entrada en esta fase
viene representada, típicamente, por un Árbol Sintáctico, un Árbol de Sintaxis Abstracta, o una Representación
Intermedia; la máquina destino puede ser un microprocesador o una máquina abstracta tal como una máquina
virtual o un lenguaje intermedio, legible por un humano. Compiladores más sofisticados realizan múltiples
traducciones en cadena (pipelining) con el fin de poder construir código para múltiples plataformas y evitar tener
que construir todas las capas del compilador.
En términos más generales, la generación de código: es usada para construir programas de una manera automática
evitando que los programadores tengan que escribir el código a mano. La generación de código puede realizarse en
tiempo de ejecución, Tiempo de carga, o Tiempo de compilación. Los compiladores JIT (Just In Time) son un ejemplo
de generadores de código.