Hay una pregunta que me persigue desde que volví a programar para Amiga: ¿por qué tiene que ser tan complicado? No me malinterpretéis, programar en C tiene su encanto. Pero cuando llevas media hora peleándote con
1 | AllocMem |
,
1 | FreeMem |
, punteros a estructuras de Intuition y castings por todas partes, te preguntas si no habrá una forma más directa de decirle al Amiga lo que quieres que haga. Sin perder el control, pero sin tener que escribir como si estuvieras rellenando formularios de Hacienda.
Pues de esa frustración nació Dash (Development Amiga Synthesis Hub), un lenguaje de programación que transpila a C para generar ejecutables nativos de AmigaOS. La idea es simple: escribes en un lenguaje limpio y legible, y Dash se encarga de generar el C necesario para que
1 | m68k-amigaos-gcc |
lo compile a un binario 68000 de toda la vida. Sin intérpretes, sin máquinas virtuales, sin runtime. El Amiga ejecuta código nativo, como debe ser.
¿Y cómo se ve?
La sintaxis está inspirada en Ruby y Python, porque si algo he aprendido después de pasar por el Basic del ZX Spectrum y el MSX, ensamblador del 8088, Cobol, Turbo Pascal, QuickBasic, Clipper, Delphi, C, C#, PHP, Ruby, JavaScript y Python es que la legibilidad no es un lujo, es una necesidad. Un programa en Dash tiene este aspecto:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 Window MainScreen
title "Mi primer programa"
width 320
height 200
end
func saludar(nombre: String) -> String
return "Hola, " + nombre + "!"
end
Main
MainScreen.open
mensaje = saludar("Amiga")
gfx_pen(1)
gfx_text_at(50, 50, mensaje)
EventLoop
On Close
Stop
end
end
end
Eso de ahí arriba abre una ventana de Intuition, escribe un texto con la función gráfica del sistema operativo y espera a que el usuario la cierre. Todo eso, en C puro, serían unas cuantas decenas de líneas con includes, estructuras
1 | NewWindow |
, llamadas a
1 | OpenWindow() |
, bucle de mensajes IDCMP, y el correspondiente
1 | CloseWindow() |
con liberación de memoria. Aquí son quince líneas. Y lo que es mejor: el C generado es correcto, compilable y optimizado.
Cómo funciona por dentro
El compilador está escrito en Python y sigue un pipeline bastante clásico:
- El código fuente
se parsea con Lark, un generador de parsers LALR para Python.1.dash
- Un transformer convierte el árbol de parseo en un AST (árbol de sintaxis abstracta) con nodos tipados.
- El analizador semántico hace las comprobaciones de tipos, resuelve scopes y valida que todo tenga sentido.
- El generador de código recorre el AST y escupe código C listo para compilar.
- Se compila con
y opcionalmente se convierte de ELF a formato Hunk con1m68k-amigaos-gcc.1elf2hunk
Todo el proceso se lanza con un solo comando:
1 | ./dash ejemplo.dash -o bin/ejemplo |
. Y ya tienes un ejecutable nativo de Amiga.
161 funciones del AmigaOS integradas
Esta es la parte de la que más orgulloso estoy, y a la vez la que más trabajo me ha dado. Dash incluye más de 160 funciones built-in que mapean directamente a las bibliotecas del AmigaOS:
- Gráficos: primitivas de dibujo, colores, texto, blitting, doble buffer, Copper, sprites hardware y BOBs.
- Sonido: reproducción de samples por los canales de Paula, carga y reproducción de módulos.
- Entrada: teclado, ratón y joystick.
- Sistema de ficheros: lectura, escritura, listado de directorios.
- Memoria: gestión de Chip RAM y Fast RAM.
- GUI: soporte para GadTools y ReAction (AmigaOS 3.2+).
No son wrappers genéricos: cada función genera exactamente las llamadas C que necesita, con las estructuras correctas y la gestión de memoria adecuada. Cuando escribes
1 | gfx_circle(160, 100, 50) |
, el código C generado usa
1 | DrawEllipse() |
de la graphics.library con los parámetros del RastPort de tu ventana. Sin magia, sin overhead.
La escotilla de emergencia: @native y @extern
Una cosa que tenía clarísima es que el lenguaje no podía ser una jaula. Cuando necesitas hacer algo que Dash no cubre (todavía), puedes incrustar C directamente con bloques
1 | @native |
, o declarar funciones externas con
1 | @extern |
para enlazar con tus propias bibliotecas. Es la típica escotilla de emergencia que todo lenguaje de alto nivel necesita cuando trabaja cerca del hardware. Y en el Amiga, trabajas cerca del hardware quieras o no ;-)
Structs, enums, módulos y lo que falta
El lenguaje ya soporta estructuras con campos tipados, enumeraciones con valores numéricos, un sistema de módulos con
1 | import |
y protección contra importaciones circulares, arrays dinámicos, type hints opcionales y scoping léxico. Vamos, que no es un juguete. Lo que falta por implementar es la parte de OOP más avanzada (herencia, polimorfismo), tipos genéricos y pattern matching. Todo llegará, pero sin prisas.
También tengo una suite de 30 tests que cubren desde las operaciones básicas hasta la generación de gráficos y audio. Cada vez que toco algo del compilador, los ejecuto todos para asegurarme de que no he roto nada. Que me conozco.
¿Por qué otro lenguaje?
Ya sé lo que estáis pensando: «¿otro lenguaje de programación? ¿En serio?». Y sí, tiene todo el sentido del mundo que os lo preguntéis. Hay miles de lenguajes y la mayoría mueren en el olvido. Pero Dash no pretende competir con Rust ni con Go. Su razón de ser es otra muy distinta.
El Amiga tiene un problema que no se resuelve con nostalgia: su Workbench necesita aplicaciones modernas. No más demos, no más pruebas de concepto, no más ports a medio terminar. Aplicaciones de escritorio reales, completas, que un usuario pueda instalar y usar en su día a día. Y eso no va a pasar mientras la barrera de entrada para programar en AmigaOS sea pelearte con C a pelo, GadTools a mano y gestión de memoria manual para cualquier ventanita con cuatro botones.
Dash es mi intento de bajar esa barrera. Si conseguimos que crear una aplicación con ventanas, menús, gadgets y acceso al sistema de ficheros sea algo que se pueda hacer en una tarde en lugar de en una semana, quizás empecemos a ver un Workbench con más herramientas útiles y menos pantallas de «insert disk». Programar juegos y demos está muy bien, y Dash también sirve para eso, pero lo que de verdad me quita el sueño es inundar el Workbench de software nuevo. Esa es la aportación que quiero hacer.
MUI, un diseñador visual y VS Code
Pero un lenguaje solo no basta. Para crear aplicaciones de escritorio en serio hace falta un toolkit de interfaz que esté a la altura, y en el Amiga ese toolkit es MUI (Magic User Interface). Así que estoy preparando soporte nativo de MUI en Dash, además del que ya existe para GadTools y ReAction. La idea es que puedas definir una interfaz MUI completa desde Dash sin tener que lidiar con las clases BOOPSI a mano.
Y aquí viene la parte que más me entusiasma: estoy desarrollando una extensión para VS Code que incluirá un diseñador visual de interfaces MUI. Algo parecido a lo que Glade es para GTK: arrastras ventanas, botones, listas y paneles, los colocas donde quieres, y la extensión genera el código Dash correspondiente. Diseñar la interfaz gráficamente y que el código se escriba solo. Para alguien que ha montado interfaces GadTools a base de calcular coordenadas a ojo, esto es casi ciencia ficción ;-)
La extensión también incluirá resaltado de sintaxis para Dash, que parece un detalle menor pero marca una diferencia enorme en la experiencia de desarrollo. Y poco a poco iré añadiendo más funcionalidades inspirándome en proyectos como Amiga DevBench, que integra depuración remota, inspección de memoria y control de procesos del Amiga directamente desde el editor a través de MCP. La idea a futuro es que puedas escribir código Dash en VS Code, diseñar la interfaz visualmente, compilar, desplegar en el Amiga (emulado o real) y depurar, todo sin salir del editor.
Y aquí es donde todo empieza a encajar: el perfil Dev Station de AmiCachy (repo en GitHub), que ya os presenté en otro post, está pensado precisamente para esto. Un entorno donde VS Code y Amiberry conviven lado a lado con carpetas compartidas. La idea es que Dash, la extensión de VS Code y AmiCachy se integren para ofrecer un flujo de desarrollo completo: escribes y diseñas en VS Code, compilas, y el resultado aparece directamente en el Amiga emulado que tienes al lado. Sin copiar ficheros a mano, sin cambiar de máquina. Un ciclo de desarrollo tan fluido como el que tienes en cualquier plataforma moderna, pero para el Amiga.
El proyecto ya está publicado en GitHub: github.com/FreeMEM/dash. Podéis echarle un vistazo, descargarlo, probarlo y, por supuesto, contribuir si os apetece. ¡Toda ayuda es bienvenida!
Iré contando los avances por aquí.
Ole tú.