¿Qué es un compilador?

Mujer trabajando desde casa en el ordenador

Autores

Josh Schneider

Staff Writer

IBM Think

Ian Smalley

Staff Editor

IBM Think

¿Qué es un compilador?

Un compilador es un tipo de programa informático que convierte el código de un lenguaje de programación (el lenguaje de origen) a otro lenguaje de programación (el lenguaje de destino).

Los compiladores se utilizan para transformar el código fuente de alto nivel en código de destino de bajo nivel (como lenguaje ensamblador, código objeto o código máquina) preservando la funcionalidad del programa.

Herramienta crítica para la programación informática moderna y práctica, los compiladores permiten a los programadores trabajar en código de alto nivel legible por humanos y luego convertir su código fuente en código objetivo ejecutable. Los compiladores también ayudan a los desarrolladores de software a crear programas ejecutables eficientes con seguridad, estabilidad y portabilidad mejoradas. Esto se debe a que los compiladores ayudan a identificar y abordar los errores, creando así aplicaciones ejecutables portátiles. 

Aunque todos los compiladores convierten el código de alto nivel en código ejecutable de bajo nivel, se utilizan distintos tipos de compiladores para diferentes lenguajes de programación y aplicaciones. Por ejemplo, se utiliza un compilador cruzado para producir código para un tipo de CPU o sistema operativo diferente de aquel en el que se ejecuta.

Cuando no se dispone del compilador ideal, o aún no se ha creado, se utiliza un compilador bootstrap para compilar un compilador más permanente que esté mejor optimizado para compilar cualquier lenguaje de programación específico.

Una breve lista de otro software relacionado incluye:

  • Los descompiladores funcionan como compiladores inversos y convierten código de bajo nivel en lenguajes de alto nivel.
  • Los compiladores de código fuente a código fuente (o transpiladores) convierten código de alto nivel en otros lenguajes de alto nivel.
  • Los reescritores de lenguaje convierten expresiones de código formal en diferentes formas sin cambiar el lenguaje.
  • Los compiladores de compiladores se utilizan para crear compiladores genéricos y reutilizables o componentes de compiladores que pueden incorporarse a fines más específicos de cada proyecto.  

Las últimas novedades sobre tecnología, respaldadas por conocimientos de expertos

Manténgase al día sobre las tendencias más importantes e intrigantes del sector en materia de IA, automatización, datos y mucho más con el boletín Think. Consulte la Declaración de privacidad de IBM.

¡Gracias! Se ha suscrito.

Su suscripción se enviará en inglés. Encontrará un enlace para darse de baja en cada boletín. Puede gestionar sus suscripciones o darse de baja aquí. Consulte nuestra Declaración de privacidad de IBM para obtener más información.

Cómo funcionan los compiladores

En la práctica, usar un compilador puede ser tan simple como introducir un comando en una línea de comando en cualquier sistema Linux (o equivalente), especificando el archivo ejecutable del compilador y los archivos fuente que se compilarán. Este comando indica al sistema que procese el código fuente, compilándolo en un código máquina de destino y generando los archivos objeto necesarios para producir un programa ejecutable. 

Los compiladores de código abierto, como GNU Compiler Collection (GCC) (una sólida colección de compiladores C que se utiliza habitualmente para compilar código C en programas C) o la alternativa Clang, están disponibles en repositorios como GitHub. Otros compiladores pueden instalarse libremente o adquirirse a través de una amplia gama de distribuidores. También se pueden integrar en entornos de desarrollo integrado (IDE) populares, que agrupan varias utilidades para el desarrollo de software, incluidos editores de texto, documentación de API y herramientas de depuración.     

Independientemente del compilador específico que se emplee, el proceso de compilación de código implica pasar el código fuente a través de varios niveles de análisis, optimización y, en última instancia, generación de código. El código fuente pasa a través de las diferentes capas analíticas secuencialmente y se evalúa en cada paso del proceso.

Si el compilador reconoce algún problema con el código fuente, puede devolver un mensaje de error, instando a los desarrolladores a solucionar los errores identificados antes de proceder a compilar el resto del código. Generalmente, los compiladores siguen los siguientes pasos:

  1. Análisis léxico: el primer paso de la compilación consiste en pasar el código fuente por el analizador léxico del compilador, un programa que transforma los caracteres en unidades significativas del lenguaje, como palabras clave, identificadores y operadores conocidos. Estas unidades se conocen colectivamente como tokens. Este paso básicamente prepara el código fuente para los próximos pasos convirtiendo elementos significativos e importantes del código fuente en tokens con los que puede trabajar el compilador. 
  2. Análisis sintáctico: el segundo paso del proceso de compilación envía los tokens del analizador léxico al analizador sintáctico del compilador. Un analizador sintáctico es un programa que comprueba el código en busca de errores sintácticos y se asegura de que el código fuente sigue correctamente las reglas del lenguaje fuente. Si el analizador sintáctico no detecta errores durante el análisis, genera una representación abstracta de la estructura global del código denominada árbol sintáctico abstracto (AST).
  3. Análisis semántico: después de verificar la sintaxis del código, un compilador realiza un análisis semántico del código analizado para deducir la función prevista del código fuente. En este paso, el compilador realiza comprobaciones de errores lógicos como variables no declaradas o uso incorrecto del operador.
  4. Optimización: aunque no es necesariamente necesaria para producir código funcional, la optimización es un paso opcional común a muchos compiladores para mejorar el rendimiento general del código compilado. La optimización puede identificar y eliminar código innecesario y dar como resultado programas más rápidos, eficientes y estables, así como acortar el proceso final de depuración. 
  5. Generación de código: en el paso final del proceso, el compilador convierte el AST en código legible por máquina. El resultado final de la generación de código es un código en lenguaje ensamblador que luego puede convertirse en código binario y ser ejecutado por el sistema informático. 
AI Academy

Cómo prepararse para la IA con la nube híbrida

El plan de estudios, dirigido por los principales líderes de pensamiento de IBM, está diseñado para ayudar a los líderes empresariales a adquirir los conocimientos necesarios para priorizar las inversiones en IA que pueden impulsar el crecimiento.

Estructura del compilador de tres etapas

Puede que algunos compiladores no sigan estrictamente la estructura anterior. Sin embargo, aunque algunos compiladores pueden contener más o menos pasos, todas las fases de la compilación pueden atribuirse a una de estas tres etapas: un front end, un middle end y un back end.

Esta estructura de tres etapas permite a los compiladores adoptar un enfoque modular. Permite combinar múltiples front ends para diferentes lenguajes con back ends para diferentes CPU, a la vez que comparte las capacidades de optimización de varios middle ends aplicables.

Las tres etapas de un compilador implican la siguiente distribución:

  1. Front-end: el front-end de un compilador incluye aspectos de análisis léxico, análisis sintáctico y análisis semántico. Esta fase verifica la sintaxis y la semántica según las reglas del lenguaje de origen y puede identificar y localizar los errores en el código fuente. Suponiendo que no se encuentre ningún error, el front end del compilador convierte el código fuente en una representación intermedia (IR) (una conversión temporal de nivel inferior del código fuente) para el middle end. 
  2. Middle end: el middle end de un compilador realiza varias optimizaciones de código en el IR independientemente de la arquitectura de CPU a la que se dirija el proceso de compilación general. Al promulgar optimizaciones en el código fuente independientemente del código máquina de destino, el compilador puede aplicar optimizaciones generalizadas que pueden mejorar el rendimiento del código en varias versiones. Estas mejoras se pueden realizar independientemente del idioma específico compatible o la arquitectura de hardware. 
  3. Back end: la etapa de back end utiliza el resultado de la etapa de middle end y puede realizar otras optimizaciones y conversiones específicas de la CPU. En esta etapa final del proceso de compilación, el compilador produce código ensamblador dependiente del objetivo, incluidas las asignaciones de registros y la programación de instrucciones. La etapa de back end suele dar resultados en un código máquina especializado para los sistemas operativos y el hardware de destino. 

Beneficios de utilizar un compilador

Si bien los compiladores no son necesarios de forma explícita para producir código que funcione, la amplia variedad y complejidad de los lenguajes de codificación y los entornos de máquinas hacen que los compiladores sean una necesidad práctica para crear software ejecutable. Estas son los cuatro principales beneficios de usar compiladores de software.

Facilitan la codificación de lenguajes de alto nivel

Los lenguajes de programación de alto nivel utilizan sintaxis y palabras clave que están más cerca de los lenguajes hablados, lo que los hace mucho más fáciles de usar para los desarrolladores. Los compiladores convierten este código legible por el ser humano en el código máquina más complejo necesario para ejecutar aplicaciones de software optimizadas.

Algunos ejemplos de lenguajes de alto nivel incluyen los siguientes lenguajes:

  • Python (utilizado para desarrollo web, ciencia de datos y otros)
  • Java™ (utilizado para el desarrollo de Android, aplicaciones empresariales y otros)
  • C++ (utilizado para el desarrollo de juegos, sistemas operativos y otros)
  • JavaScript (utilizado para el desarrollo web dinámico e interactivo)
  • PHP (utilizado para escribir scripts del lado del servidor en el desarrollo web)
  • C# (usado para aplicaciones de Windows, desarrollo de juegos con motor Unity)
Reducen la repetición

Los compiladores ayudan a mejorar la eficiencia al convertir código de alto nivel en código de máquina ejecutable. El resultado del compilador se almacena con una extensión de archivo .exe, que luego se ejecuta directamente en un ordenador. Gracias al compilador, escribir un programa ejecutable se convierte en una tarea que solo hay que realizar una vez.

Una vez completado, el código compilado se puede ejecutar tantas veces como sea necesario. Este proceso ayuda a que los programas se ejecuten en general de forma más rápida y eficiente, ya que ciertas aplicaciones o partes de aplicaciones pueden ejecutarse independientemente de las tareas de software en tiempo de ejecución.

Mejoran la portabilidad

No todos los sistemas pueden ejecutar todos los tipos de código de programación. Los compiladores se utilizan para convertir los tipos de código que los desarrolladores prefieren utilizar en los tipos de código que los sistemas necesitan para funcionar. De esta forma, los compiladores mejoran la portabilidad de los programas al convertir el software a una amplia variedad de lenguajes compatibles que se pueden almacenar, transferir y ejecutar fácilmente en varios sistemas operativos y arquitecturas de hardware.

Promueven la optimización general

Durante el proceso de compilación, los compiladores se pueden usar para identificar y abordar errores y fallos de software, lo que da como resultado programas más estables y mejor optimizados. Los compiladores también pueden ayudar a mejorar la seguridad del software al prevenir errores relacionados con la memoria, como desbordamientos de búfer, y generar advertencias si se detectan posibles problemas de memoria. 

Compiladores versus intérpretes

Mientras que los compiladores se utilizan para convertir el código fuente en código máquina ejecutable, los intérpretes son otro tipo de programa que puede proporcionar una funcionalidad similar, pero a través de un mecanismo diferente.

En lugar de convertir el código fuente, los intérpretes ejecutan directamente el código fuente o utilizan un código intermedio conocido como código de bytes, una representación del código fuente de bajo nivel e independiente de la plataforma. El código de bytes actúa como intermediario entre el código fuente legible por los humanos y el código de máquina, y está diseñado para que lo ejecute una máquina virtual (VM) en lugar de directamente en el hardware de un ordenador. 

En teoría, cualquier lenguaje de programación puede ejecutarse con un compilador o un intérprete. Sin embargo, los lenguajes de programación individuales tienden a adaptarse mejor a la compilación o a la interpretación.

En la práctica, la distinción entre lenguajes compilados e interpretados puede resultar a veces difusa, al igual que la distinción entre compiladores e intérpretes, ya que ambos tipos de programas pueden presentar funcionalidades que se solapan. Aunque algunos lenguajes se compilan con mayor frecuencia y otros se interpretan más a menudo, es posible escribir un compilador para un lenguaje que se interpreta habitualmente y viceversa.

Los lenguajes de alto nivel suelen crearse teniendo en cuenta un tipo de conversión, ya sea la compilación o la interpretación, pero se trata más de sugerencias que de limitaciones estrictas. Por ejemplo, BASIC suele denominarse lenguaje interpretado y C lenguaje compilado, pero existen compiladores para BASIC al igual que intérpretes de C. 

La principal diferencia entre intérpretes y compiladores radica en la sincronización y la optimización. Ambos tipos de programas intentan convertir el código fuente en código de destino que primero sea funcional y luego optimizado.

Dependiendo del entorno operativo, el código compilado o interpretado puede ser más adecuado para ejecutarse de manera eficiente teniendo en cuenta la capacidad del hardware, la memoria y la capacidad de almacenamiento. Dependiendo de las limitaciones de cualquier programa, aplicación y hardware específicos, la compilación, la interpretación o una combinación de ambas pueden dar los mejores resultados. 

Como tal, la interpretación no puede sustituir por completo a la compilación, pero puede mover las tareas de compilación a un segundo plano mediante un proceso de conversión gradual. Los compiladores emplean una estrategia de conversión anticipada (AOT) que convierte el código fuente en código de destino por completo antes de crear un archivo ejecutable.

Los intérpretes, por su parte, ejecutan el código directamente según lo requiera la aplicación o utilizan bytecode como intermediario para generar código fuente ejecutable en la máquina virtual. De esta manera, los intérpretes pueden proporcionar algunas aceleraciones o flexibilidad, pero en algún momento, se debe proporcionar un conjunto de instrucciones de máquina ejecutadas directamente hacia el final de la pila de ejecución.

En algunos casos, cuando la eficiencia ligera es una prioridad, los intérpretes especiales pueden ser preferibles a los compiladores por su capacidad para realizar conversiones justo a tiempo (JIT). JIT es una estrategia que compila fragmentos de código fuente en código de destino en un búfer de memoria para su ejecución inmediata. La interpretación JIT compila el código bajo demanda, combinando la eficiencia de compilación única de un compilador tradicional con la flexibilidad de ejecutar código repetidamente, a menudo más rápido que los intérpretes de código de bytes estándar.

Sin embargo, a medida que aumentan las tendencias modernas hacia la compilación JIT junto con la interpretación de bytecode dependiente de la situación, muchos compiladores se están diseñando para ofrecer características tanto de compilación como de interpretación. Esta superposición difumina aún más las líneas entre estas dos categorías. 

Soluciones relacionadas
IBM Cloud Infrastructure Center 

IBM Cloud Infrastructure Center es una plataforma de software compatible con OpenStack para gestionar la infraestructura de las nubes privadas en IBM zSystems e IBM LinuxONE.

Explorar Cloud Infrastructure Center
Soluciones de infraestructura de TI

Descubra servidores, almacenamiento y software diseñados para su estrategia empresarial de nube híbrida e IA.

Explore las soluciones de infraestructura de TI
Soluciones de infraestructura en la nube

Encuentre la solución de infraestructura en la nube adecuada para las necesidades de su empresa y escale los recursos según la demanda.

Soluciones en la nube
Dé el siguiente paso

Transforme la infraestructura de su empresa con las soluciones de nube híbrida y preparadas para la IA de IBM. Descubra servidores, almacenamiento y software diseñados para asegurar, escalar y modernizar su empresa o acceda a conocimientos de expertos para mejorar su estrategia de IA generativa.

Explore las soluciones de infraestructura de TI Descargue el libro