Cómo construí un lenguaje de programación El camino (difícil) hacia el éxito

Construcción de un lenguaje de programación el camino hacia el éxito

Francamente, difícil es un eufemismo.

Mi artículo anterior sobre mi lenguaje de programación describió su sintaxis y proporcionó una idea general de cómo lo construí.

Pero decidí escribir otro dedicado a mi viaje hacia el resultado final, porque si soy honesto, el viaje ciertamente tuvo muchas más dificultades que éxitos, y los desafíos que tuve que superar fueron realmente intimidantes. Espero que este artículo también sirva de motivación para cualquier persona que emprenda un proyecto similar y enfrente dificultades similares, para que no se rinda y en cambio sepa que alguien más estuvo una vez en la misma posición que ellos y logró cumplir su objetivo.

Pero, ¿por qué debería importarte?

Después de todo, todos ustedes provienen de diversos campos, ya sea ciencia de datos o simplemente buenos y viejos Python y Java.

Bueno, incluso si no estás interesado en construir tu propio lenguaje de programación, muchas de las habilidades blandas que mejoré durante esta experiencia seguramente serán comprensibles (y espero que motivadoras) para todos ustedes, especialmente si están interesados en la programación.

¿Cuántas veces escribes un programa en el que cada línea parece correcta y en su lugar recibes un error críptico que parece casi imposible de depurar, momento en el que comienzas a perder tu motivación y piensas en rendirte?

Foto de Tim Gouw en Unsplash

Bueno, me enfrenté a esos problemas tan comunes demasiadas veces mientras construía el lenguaje, y la forma en que finalmente los superé y perseveré espero que comunique un mensaje memorable a medida que avanzas en el artículo.

Comenzando

La idea original para esto surgió cuando estaba en el octavo grado (o noveno grado, no puedo recordar exactamente), pero en ese entonces apenas entendía las condicionales y los bucles iterativos, así que lo olvidé.

Pero años después, la misma idea se reavivó en mi mente, excepto que no tenía ni idea de cómo empezar.

Foto de Towfiqu barbhuiya en Unsplash

Entonces, como todas las demás cosas que no sabía hacer, busqué en Google

“Cómo crear tu propio lenguaje de programación”.

Y bueno, los resultados fueron bastante prometedores. Pasé mucho tiempo revisando cada uno de ellos línea por línea y capté la esencia:

Existen dos tipos de lenguajes: interpretados y compilados. Los lenguajes interpretados tienden a ser más simples de construir, pero son más lentos. Por otro lado, los lenguajes compilados convierten tu código en código de máquina y luego lo ejecutan (los lenguajes compilados suelen ser más rápidos).

El proceso general para construir un lenguaje es:

  • Definir el propósito y la sintaxis del lenguaje: Esto fue bastante fácil para mí (sabía que quería construir un lenguaje relacionado con las matemáticas) y para ahorrarme trabajo y también hacer que el lenguaje sea lo más de alto nivel posible, decidí mantener solo algunas funciones (esenciales y útiles) y solo dos variables, una función y un número de punto flotante.
  • Construir un analizador léxico y un analizador sintáctico: Un analizador léxico es el primer componente de cualquier lenguaje y coloca cada palabra/frase de tu código en diferentes categorías (como palabras clave, operadores, comentarios, etc.). Pero por sí solos, estos lexemas no tienen sentido y para entenderlos, uno necesita construir un analizador sintáctico. El analizador sintáctico asegura que los lexemas sigan la sintaxis del lenguaje y los coloca en un AST (árbol de sintaxis abstracta).
  • Ejecutar código: Cada nodo en el AST representa uno de los tokens recopilados por nuestro analizador léxico original, y esto incluye también los nombres de las funciones. Por lo tanto, al ejecutar nuestro AST, podemos ejecutar el código escrito línea por línea; esta es la base general para un lenguaje de programación interpretado.

Pero un compilador requiere algunos pasos adicionales; necesitas usar bibliotecas populares como LLVM y libgccjit, que convierten el código en un archivo ejecutable compilado.

¿Compilado o interpretado?

Por un lado, podría crear un lenguaje interpretado, lo cual es bastante desafiante y requiere que dedique una gran cantidad de tiempo y esfuerzo. Por otro lado, podría crear un lenguaje compilado, lo cual es aún más desafiante y requiere que dedique aún más tiempo y esfuerzo.

Pero la idea de construir mi propio lenguaje compilado simplemente me parecía demasiado atractiva, y caí en la trampa.

Consejo: no lo hagas.

Aunque hay recursos disponibles sobre cómo construir un compilador utilizando LLVM (definitivamente recomiendo ver el video de 100 segundos sobre LLVM, tanto entretenido como educativo), rápidamente me perdí en su documentación debido a lo complejo que era.

Apostaría y diría que probablemente podrías aprender los conceptos básicos de Java más rápido que aprender los conceptos básicos de construir un compilador con LLVM.

Foto de Emile Perron en Unsplash

¿Una pérdida de tiempo colosal (o no)?

Desafortunadamente para mí, pasé más de dos meses intentando abrirme camino a través de LLVM primero, y luego libgccjit. Este último resultó más prometedor e incluso escribí código para el compilador, sin embargo, luego me enfrenté a una multitud de problemas relacionados con la configuración del paquete libgccjit; llegué al punto de descargar el código fuente completo desde GitHub y colocarlo en el mismo directorio que mi código de compilador. Pero aún así, nada parecía funcionar. Pasé por innumerables hilos de Reddit y StackOverflow, pero sin éxito.

Cuando StackOverflow no puede ayudarte, sabes que algo está muy mal.

Al borde de rendirse

En este punto, realmente había tocado fondo, porque no había progresado en mucho tiempo, y empecé a desvalorizar todo el trabajo que había hecho, como construir un analizador léxico y un analizador sintáctico desde cero, sin utilizar las populares herramientas lex/yacc y flex/Bison. En ese momento, me pregunté “¿Debería tirarlo todo a la basura (virtual)?”. Estuve tentado de decir que sí, pero no renuncio tan fácilmente, especialmente cuando se trata de proyectos relacionados con la programación.

Así que salí a caminar, despejé mi mente y volví a empezar, esta vez con un objetivo diferente: construir un lenguaje interpretado.

Finalmente, completándolo.

Una vez que decidí que construiría un intérprete, también tomé la difícil decisión de abandonar C y volver a Python. En circunstancias normales, es mejor utilizar lenguajes de nivel inferior para construir lenguajes interpretados, ya que su velocidad compensa la lentitud del intérprete.

Pero estaba en un momento desesperado, y eso requiere medidas desesperadas.

Después de regresar a India, pasé la siguiente semana sin dormir, y literalmente trabajé 24 horas al día (alrededor de 21 si no contamos el desayuno, el almuerzo y la cena, soy un comedor lento).

Y lo que sucedió después es algo que me ocurrió por primera vez, y probablemente nunca vuelva a suceder: ¡mi código funcionó en el primer intento! Sin depuración, sin más confusiones.

Cuando ejecuté mi código fuente, cada componente: desde el analizador léxico, hasta el analizador sintáctico y el AST, funcionaron correctamente y ejecutaron cada línea de código como debían.

Foto de the blowup en Unsplash

Reflexión y una nota final

La cita anterior puede sonar cliché, pero eso no resta validez; enfrenté muchas más fallas que éxitos mientras construía AdvAnalysis, pero, sin embargo, terminé en la cima.

Aunque podrías aprender sobre cosas a tener en cuenta al construir tu propio lenguaje de programación (como compilado vs interpretado, el proceso a seguir), la lección principal que aprendí (y espero que tú también hayas aprendido) es que no importa cuán desalentador pueda ser encontrar constantemente un error críptico en tu programa, al final, siempre funciona como esperas, si tienes la capacidad de ser paciente y volver al punto de partida y seguir un enfoque diferente.

Para ser honesto, como entusiasta de la programación, probablemente ya lo sabías. 🙂

We will continue to update Zepes; if you have any questions or suggestions, please contact us!

Share:

Was this article helpful?

93 out of 132 found this helpful

Discover more

Inteligencia Artificial

Esta investigación de IA de China presenta Consistent4D Un nuevo enfoque de inteligencia artificial para generar objetos dinámicos en 4D a partir de videos monocu

El campo de la visión por computadora se enfrenta a una tarea fundamental pero ardua: descifrar datos tridimensionale...

Inteligencia Artificial

La Huella de Carbono de la Inteligencia Artificial

Buscando formas de reducir la emisión de gases de efecto invernadero atribuibles al uso de la inteligencia artificial...

Inteligencia Artificial

Engañando a los clasificadores forenses El poder de los modelos generativos en la generación adversarial de rostros

Los avances recientes en el Aprendizaje Profundo (DL), específicamente en el campo de las Redes Generativas Adversari...

Inteligencia Artificial

Investigadores de Microsoft proponen DeepSpeed-VisualChat Un salto adelante en el entrenamiento de modelos de lenguaje multi-modal escalables.

Los modelos de lenguaje grandes son sistemas de inteligencia artificial sofisticados creados para comprender y produc...