Después de escribir el primer artículo sobre cómo crear tu propio sistema operativo, alguien me dijo que si podía hacer un artículo sobre cómo crear un lenguaje de programación. Al principio no hice mucho caso, pero ahora y por otros caminos he aprendido bastante más sobre la creación de los lenguajes de programación. Así pues, vamos a hacer un lenguaje de programación básico, fácilmente empotrable en otros programas y que funcione con una máquina virtual que también diseñaremos. Hoy nos toca hacer la máquina virtual más básica.
Probablemente te preguntes: «¿una máquina virtual? ¿Pero eso no es muy difícil y además ralentiza los programas?» Al contrario, una máquina virtual simple es muy sencilla y relativamente rápida. He elegido Rust como lenguaje para la máquina virtual. Pero, ¿qué es Rust?
Rust se instala en Linux de manera sencilla. Sin embargo, no hay paquetería oficial. Los usuarios de Ubuntu pueden agregar estos dos PPA: ppa:hansjorg/rust y ppa:cmrx64/cargo, los usuarios de Arch pueden usar AUR (cargo-git es el paquete que instala todo). El resto pueden usar:
curl -s https://static.rust-lang.org/rustup.sh | sudo sh
¿Cómo funciona una máquina virtual?
Si sabes como funciona el mundo en ensamblador es exactamente igual, con el stack o la pila. Si no, te lo explico. Imaginémonos el siguiente código:
print 2+3
El ordenador no entiende lo que significa 2+3, ni tampoco sabe qué orden hay que seguir. Los ordenadores funcionan con pilas o stacks en los que se van acumulando datos y se van sacando continuamente. Ese código en nuestra máquina virtual debería ser algo parecido a esto:
PUSH 2 PUSH 3 ADD PRINT
Básicamente, pondríamos el 2 en la pila en lo alto, el 3 también. ADD sacaría (es decir, lo elimina de la pila y obtiene su valor) los 2 últimos elementos de la pila y añadiría el resultado en lo alto de la pila. PRINT cogería el último elemento de la pila y lo usaría para mostrárnoslo. Ahora hagamos eso en Rust.
Primeramente deberemos definir un lenguaje para el Bytecode, podríamos usar uno ya existente como el de Java o el CLR de .NET/Mono, pero vamos a crear nosotros uno más básico.
https://gist.github.com/a01de8904fd39a442c20
Usamos notación hexadecimal para cada instrucción. En lo alto hemos puesto #[deriving(FromPrimitive)], es una particularidad de Rust y nos servirá para más tarde poder comparar la enumeración con bytes directamente.
Ahora debemos hacer una función que ejecute cada una de esas instrucciones. Para ello debemos leer un byte y compararlo con las instrucciones que tenemos en la enumeración. Si se encuentra alguna que exista se debe ejecutar su acción.
https://gist.github.com/8950ce212a2de2f397f9
Eso hacemos para leer cada byte individualmente y para ejecutarlas:
https://gist.github.com/12e24a1f0dd65e4cd65d
Como vén, diferenciamos si antes se nos dio la orden de PUSH (nuestra orden INTEGER), el siguiente byte será llevado completamente a la pila. Ahí estamos usando dos funciones que no les he enseñado, self.pop() y self.push(), que se encargan obviamente de manejar el stack.
https://gist.github.com/54147f853a8a2b8c01d9
No son muy complejas, pero la función de pop tiene mecanismos de detección de errores. De hecho, en Rust, si quitásemos esos mecanismos nos daría un error de compilación. Ahora simplemente debemos llamar en un programa a Perin (nuestra máquina virtual) y que ejecute un bytecode.
https://gist.github.com/99b1ab461318b3a644d0
Ese bytecode puede ser leído de un fichero, pero aquí para simplificar lo he almacenado en una variable. Si lo ejecutamos nos dará el resultado esperado:
Perin v0.1 Perin VM executes FlopFlip bytecode Starting PerinVM instance PerinVM v0.1.0 Integer value 5
Todo el código está disponible en GitHub bajo la Apache License 2.0: https://github.com/AdrianArroyoCalle/perin. Para compilar deben tener Cargo instalado y poner:
cargo build && ./target/main
En el siguiente capítulo veremos más sobre nuestro lenguaje de programación.
Interesante curiosidad , aunque no sea muy util en realidad , no esta de mas saberlo .
Es genial que le hagas publicidad a Rust , es un lenguaje que promete mucho no solo es mas seguro que c++ , sino que (de momento) mas claro en su sintaxis .
En cuanto a foto , yo no consideraria java evolución XD.
Y de fortran , nunca lo use , pero no he oido muchas cosas buenas de el …
Yo sí, y es especialmente útil en ingeniería si bien Python se está abriendo lugar.
Fortran es quizás el otro gran lenguaje junto con C. Todavía hoy en cuestiones realmente críticas estarán uno u otro.
Y resultaría discutible que Fortran esté como ‘evolución’ de C, cuando quizás debería ser al revés, por ser C más nuevo, moderno y con más posibilidades; aunque uno no se desprende del otro en lo más mínimo.
Aunque los puestos finales todos son discutibles desde algún punto de vista.
+1 a lo de Java
A ver si me gusta esto que le doy algo a la programación pero básico a ver si entiendo más.
¿Cual proposito realmente tiene crear un lenguaje de programación nuevo?, a mi personalmente me parece que es una estratagema para ocultar el codigo fuente.
Amigo que pasó con la continuación de «tu propio sistema operativo»? No lo dejes ahí por favor, continúalo.
En realidad que eres un master y justo estos dos temas han cautivado por completo mi atención, mas no quisiera que se quedaran a medio camino.
Se que muchos pensamos igual y estamos a la espera de las continuaciones y conclusiones de estos interesantísimos temas.
Muy interesante, muchas gracias. 🙂
Yo no considero a java un lenguaje de programación, mas bien un interpretador de ordenes, ya que no es compilable
[Un lenguaje de programación es un lenguaje formal diseñado para expresar procesos que pueden ser llevados a cabo por máquinas como las computadoras.]
Por esto mismo, Java es un lenguaje de programación. Incluso el lenguaje Bash (lenguaje para el intérprete de comandos de linux) es un lenguaje de programación en si mismo.
Hay dos tipos de lenguajes:
– Compilados
– Interpretados
– Mixtos (Máquinas virtuales, se compilan las librerías nativas y se interpreta el código funcional)
Los intérpretes son muy útiles a la hora de la multiplataforma y no por ello tienen un rendimiento nefasto. Java, VB.NET, C++ .NET, F#, C# son todos lenguajes mixtos. El lenguaje bash, bat, PHP, Javascript y muchos más son lenguajes interpretados.
Si no consideras Java como lenguaje porque es interpretado (cosa que no es así) no deberías considerar otros muchos lenguajes que se utilizan para hacer programas. Es más, por esa regla de tres no deberías considerar que existe ningún lenguaje de programación a excepción del propio lenguaje máquina.
Y, ¿por qué no?, ni siquiera el lenguaje máquina podría ser considerado lenguaje ya que realmente solo es un conjunto de órdenes «interpretadas» por el procesador.
Porque efectivamente, TODOS los lenguajes no son más que un conjunto órdenes que se interpretan en un procesador.
Te puede gustar más o menos un lenguaje (Java, en este caso), parecerte más o menos útil y potente pero decir que no es un lenguaje de programación porque no es compilado… va en contra de todas las definiciones de lenguaje de programación.
😐 Espero no haber parecido muy brusco
no tranquilo solo nos destruiste la vida
jjajajajaja, perdoooon. no era mi intención xD
java es un lenguaje de programacion. porque podes desarrollar una aplicacion y cuando compilas haces un .jar que es interpretado por laJVM.entonces segun tu logica python tampoco porq es iterpretado pero se compila a diferentes ejecutables…
Muy buena información
buena información pero tengo una duda, será posible crea un nuevo lenguaje de programación desde cero sin tener que depender de otras analogías o software. hablo de la misma forma en la que se otros lenguajes fueron hechos como java o el HTML.
agradecería mucho su ayuda en esta duda.