BookinglyTech News
Software

MoonForth: un Forth sobre la API C de Lua escrito sin haber hecho uno antes

Victoria Lacroix publica en Codeberg una implementación de Forth en C apoyada en la API de Lua, construida en una semana y sin experiencia previa con el lenguaje.

3 min de lecturaLobsters0 vistas

Victoria Lacroix ha publicado MoonForth, una implementación de Forth escrita en C que se apoya en la API de Lua, y lo ha hecho sin haber escrito antes un intérprete de este lenguaje. El código está en el repositorio de Codeberg y el relato del proceso, que la propia autora admite que va "mayormente de memoria", cabe en menos de una semana: tres días de trabajo desde que decidió intentarlo hasta que ejecutó la primera línea.

No encontró walkthroughs detallados para escribir un Forth propio, así que siguió la recomendación habitual en esos círculos y partió de el código de JonesForth, un Forth en ensamblador x86. Como el objetivo era C, la traducción directa no servía de mucho. Y el intérprete y el compilador de JonesForth le resultaban difíciles de seguir, así que los dejó aparcados y empezó por otro lado.

La pila de Lua como punto de entrada

El atajo estaba en una característica del propio Lua: el runtime usa internamente una pila para pasar valores entre funciones. Escribir funciones que manipulan esa pila a través del C API equivale, en la práctica, a escribir palabras del núcleo de Forth. En unas horas tenía un puñado de funciones, sin ninguna forma de ejecutarlas todavía, y a partir de ahí fue usando sus propias palabras para construir las siguientes.

El problema de fondo, cómo representar una definición, se resolvió con punteros. Una función C es un puntero, y un puntero se puede empujar a Lua como user data. Una palabra de Forth es una secuencia de otras palabras, así que una definición cabe en una tabla de punteros; y como las tablas de Lua son referencias, esas tablas se pueden anidar dentro de palabras que las usan. El intérprete solo necesita mirar el tipo de cada elemento almacenado para decidir qué hacer con él. La redefinición se comporta como en la mayoría de sistemas Forth: una palabra nueva que tapa a otra no altera lo que ya se compiló con la anterior.

Tres días después de tomar la decisión, corría la primera línea de código. El compilador llegó poco después y alinearlo con el intérprete no costó, porque ambos comparten el mismo modelo. Las palabras inmediatas salieron rápido. El control de flujo lo tomó conceptualmente de JonesForth, que lo implementa en el propio Forth a partir de palabras más simples, aunque su código no era aplicable tal cual porque MoonForth no accede directamente a las definiciones de palabras. La salida fue la de otros sistemas: escribir las palabras que permiten rellenar después las instrucciones de salto. Con eso llegaron if/else/then y los bucles, y la pestaña con el código de JonesForth se pudo cerrar. En una semana pasó de no saber cómo se escribe un Forth a implementar características del núcleo en el suyo.

Lo aprovechable aquí no es MoonForth en sí, sino la vía: apoyarse en la API C de un runtime ya existente en lugar de empezar desde cero. Para quien tenga curiosidad por el lenguaje, la autora cita el conocido artículo de Dave Gauer sobre la historia de Forth, que sigue siendo la puerta de entrada habitual.