BBim
Descripción del contenido de la página
Utilería para escribir programas para ZX Spectrum en BBim (formato mejorado de Beta BASIC) con el editor Vim.
«BBim» significa «Beta BASIC improved», esto es, «Beta BASIC mejorado». Por una parte es una utilería para escribir programas en Beta BASIC con el editor Vim; por otra, es un formato mejorado para escribir código en Beta BASIC.
Desde que empecé a interesarme por Beta BASIC y lo elegí para algún proyecto (como Alien-B o La legionela del pisto) me rondaba la idea de programar una herramienta que me permitiera desarrollar en Beta BASIC con la comodidad y eficacia de un editor como Vim, que es mi entorno de trabajo habitual. Sin embargo, pensé que sería mejor invertir ese esfuerzo en MasterBASIC para SAM Coupé, una plataforma más potente y su sucesora directa (la SAM Coupé es muy compatible con la ZX Spectrum; y MasterBASIC, como el SAM BASIC original, son obra del mismo autor que escribió Beta BASIC, Andy Wright). Cuando el proyecto MBim se mostró inviable decidí aprovechar el trabajo realizado, adaptarlo a Beta BASIC y completarlo. El resultado es BBim.
Componentes
BBim consta de los siguientes componentes:
- llist2BBim: Programa escrito en Vim para convertir al formato BBim un listado de un programa escrito en Beta BASIC.
- Beta BASIC Vim syntax file: Fichero de resaltado de sintaxis de Vim para Beta BASIC.
- BBim Vim syntax file: Fichero de resaltado de sintaxis de Vim para el formato BBim de Beta BASIC.
- BBim2BB: Programa escrito en Vim para convertir al formato estándar de Beta BASIC un código fuente de formato BBim.
- BBimport: Programa para importar en el intérprete de Beta BASIC un código fuente creado en el sistema anfitrión del emulador de ZX Spectrum.
El formato BBim
Aparte de la comodidad de trabajar con un editor tan potente y versátil como Vim, las mejoras que aporta el formato BBim en sí respecto al Beta BASIC original son las siguientes:
- Metacomandos o comandos del preprocesador.
- Comentarios de línea y de bloques como en C; metacomentarios.
- Líneas en blanco.
- Líneas partidas.
- Indentación con tabuladores o espacios indistintamente.
- Etiquetas en lugar de números de línea.
- Caracteres gráficos en formato de BASin.
- Caracteres empotrados en formato de BASin.
Metacomandos
Los metacomandos comienzan por el signo «#», deben estar al comienzo de una línea (con indentación opcional) y no deben llevar comentarios en la misma línea porque la mayoría de ellos usa como parámetros todo lo que hay tras el comando.
Es posible anular temporalmente un metacomando con un metacomentario de línea o con un comentario de línea; no así con un comentario de bloque.
Inclusión de ficheros
El metacomando #include
permite incluir un fichero en el código fuente que está siendo procesado. En la versión actual no permite usar rutas relativas y por tanto debe especificarse la ruta absoluta al fichero. Es posible usar este mismo comando en los ficheros incluidos, sin límite de niveles de anidamiento, pero debe tenerse en cuenta que no hay comprobación de recursividad.
Ejemplo:
#include ~/zx_spectrum/lldp/prueba.bbim
Este metacomando es lo primero de lo que se ocupa el preprocesador; solo cuando no hay más ficheros pendientes de incluir continúa con los siguientes pasos del proceso.
Comandos de Vim
El metacomando #vim
permite ejecutar cualquier comando de Vim.
Esto permite manipular el código fuente de cualquier forma imaginable, por ejemplo crear macros mediante sustituciones.
La utilidad más inmediata es poder usar nombres de variable largos y sustituirlos por otros cortos. Esto hace el código mucho más legible, pues Beta BASIC, al igual que Sinclair BASIC, no permite nombres largos de variables de cadena o matrices (salvo en las matrices creadas como ficheros en el disco RAM). Estas sustituciones también son útiles con las variables numéricas, pues usando nombres cortos en el código final se ahorra memoria y se gana velocidad de ejecución.
En el ejemplo que sigue se muestra cómo usar en un procedimiento la variable command$
y la matriz numbers()
, y cambiar sus nombres respectivamente por c$
y n()
en el código final:
#vim /defproc/,/endproc/substitute/\<command$/c$/g
#vim /defproc/,/endproc/substitute/\<numbers(/n(/g
defproc ejemplo command$
print command$
dim numbers(12,15)
endproc
En el ejemplo mostrado la sustitución se ciñe al siguiente procedimiento definido, pero igualmente podría ser todo el fichero o cualquier parte de él. Quien utilice BBim ha de estar por lo menos familiarizado con Vim, sus comandos y su sintaxis. Y en todo caso Vim dispone de una excelente documentación hipertextual que ofrece toda la información necesaria.
Es posible ver otros ejemplos de sustituciones en el programa BBimport 5.
Primer número de línea
Con el comando #firstline
puede definirse el primer número de línea que se usará para renumerar el programa final en Beta BASIC.
Ejemplo:
#firstline 9000
Si hay más de un comando #firstline
solo el primero será tenido en cuenta. Si no se usa este comando, el primer número de línea será el uno.
Comentarios
Una de las muchas limitaciones de programar en un BASIC interpretado en una máquina de ocho bitios es no poder comentar el código con todo el detalle necesario, debido a las limitaciones de memoria, a la incomodidad de edición y al efecto sobre la velocidad de ejecución. En programas muy complejos a veces no queda otra solución que documentar el código de forma externa. Por ello poder escribir comentarios sin ninguna limitación es tan importante en muchos casos.
El formato BBim proporciona tres nuevas opciones para comentarios:
- Metacomentarios de línea con
#
(prioridad alta: se eliminan en primer lugar). - Comentarios de línea con
//
(prioridad media: se eliminan en segundo lugar. - Comentarios de bloque con
/*
y*/
(prioridad baja: se eliminan en tercer lugar).
Los comentarios originales (con el comando REM
) pueden seguir usándose, y se mantendrán en el programa final. Son útiles para indicar el autor del código fuente, la versión, la licencia de uso y poco más.
Metacomentarios de línea
Este es el tipo de comentario de mayor prioridad, el que primero se elimina del código.
El signo «#» debe ser el primero de la línea (opcionalmente con espacios o tabuladores previos).
La función de este tipo de comentarios es poder hacer anotaciones que se refieran al propio desarrollo del código, no a su funcionamiento, así como anular temporalmente de forma clara zonas de código que puedan contener los otros tipos de comentarios.
Dado que los metacomandos, que también empiezan con el signo «#», se procesan antes que los comentarios, no existe conflicto entre ellos. Sí podría darse el caso de que al usar un metacomentario para anular temporalmente una línea de código creáramos un falso metacomando (por ejemplo al anular una línea que tuviera una llamada a un procedimiento llamado include
, lo que resultaría en #include
). Para evitarlo basta usar un espacio tras la almohadilla.
Comentarios de línea
La marca //
puede estar en cualquier lugar de la línea (incluso dentro de cadenas o expresiones).
La marca, los espacios o tabuladores que la precedan y el resto de la línea a su derecha serán eliminados.
Comentarios de bloque
La marca de inicio /*
debe estar al comienzo de una línea (opcionalmente con espacios o tabuladores previos). La marca de final */
puede estar en cualquier posición.
Todo lo que haya de una a otra marca será eliminado, y también los espacios o tabuladores que precedan a la marca de inicio.
Los comentarios de bloque no son anidables y no afectan a los metacomandos.
Líneas partidas
Una línea de código fuente puede ser dividida en más de una línea de texto. Como es habitual en otros lenguajes de programación, para indicar que una línea de código fuente continúa en la siguiente línea de texto se emplea el signo de la barra inclinada hacia la izquierda. La indentación de las líneas de texto segunda y siguientes de una línea de código dividida no es tenida en cuenta, será eliminada en la línea de código resultante. Pero los espacios antes del signo «\» sí se conservarán, y a menudo son imprescindibles, como muestra el siguiente ejemplo:
let \
m=12,\
t=15
print\
"Saluton, \
mondo!":\
stop
El código anterior en formato BBim será convertido en el siguiente código en Beta BASIC:
1 let m=12,t=15
2 print "Saluton, mondo!":stop
Etiquetas
BBim no usa números de línea sino etiquetas.
Los nombres de las etiquetas deben empezar siempre por el signo de la arroba, tanto al definirlas como al referenciarlas. El resto de caracteres pueden ser letras del alfabeto inglés, dígitos o el signo de subrayado («_»), en cualquier orden o combinación. No se hace distinción entre minúsculas y mayúsculas. No hay longitud máxima para el nombre de una etiqueta (salvo la impuesta por el lenguaje de programación de Vim, cualquiera que sea).
Para definir una etiqueta basta que su nombre esté al comienzo de una línea de código (puede haber espacios o tabuladores antes):
gosub @rutina1
stop
@rutina1
print "Rutina 1"
@espera
if not rnd then goto @espera
return
Opcionalmente, para mayor claridad, si se prefiere puede usarse el comando label
para definir las etiquetas:
gosub @rutina1
stop
label @rutina1
print "Rutina 1"
label @espera
if not rnd then goto @espera
return
Cualquier palabra que en el código fuente cumpla las condiciones para ser una etiqueta será tomada como tal, independientemente de su posición en el código. Esto permite incluir etiquetas dentro de cadenas o en cálculos, como haríamos con los propios números de línea:
gosub val "@rutina1"
print @rutina2+100*valor
Sin embargo eso puede tener efectos indeseados. Por ejemplo, dado el siguiente código:
label @blabla
print "Hola"
print "Mi correo-e es: betabasic@blablabla.info"
print "Y mi otro correo-e es: betabasic@blabla.info"
El resultado final en Beta BASIC sería el siguiente, con una sustitución indeseada en la última línea:
2 print "Hola"
3 print "Mi correo-e es: betabasic@blablabla.info"
4 print "Y mi otro correo-e es: betabasic1.info"
Para evitar esas posibles coincidencias debe usarse algún medio de camuflar la falsa etiqueta, como en los ejemplos siguientes:
rem Arroba camuflada:
print "Y mi otro correo-e es: betabasic";chr$ 64;"blabla.info"
rem Arroba separada:
print "Y mi otro correo-e es: betabasic@";"blabla.info"
Caracteres gráficos
Para representar los caracteres gráficos (GDU y gráficos de bloques, propios de la ZX Spectrum), se emplea la misma notación usada por el entorno de desarrollo BASin:
De \A
a \U
representan los veintiún GDU disponibles.
Los caracteres de bloques se representan con la misma barra inclinada y una combinación de dos de los cuatro signos siguientes: «:», «.», «'» y espacio. Con ellos es posible representar de forma fácil de recordar las cuatro partes de que consta cada uno de estos gráficos, como se muestra a continuación:
\
= vacío\::
= lleno\.:
= lleno salvo esquina superior izquierda\:.
= lleno salvo esquina superior derecha\:'
= lleno salvo esquina inferior derecha\':
= lleno salvo esquina inferior izquierda\:
= columna izquierda\ :
= columna derecha\''
= fila superior\..
= fila inferior\'
= esquina superior izquierda\ '
= esquina superior derecha\ .
= esquina inferior derecha\.
= esquina inferior izquierda\'.
= esquinas superior izquierda e inferior derecha\.'
= esquinas inferior izquierda y superior derecha
Octetos empotrados
Es posible insertar en el código fuente cualquier octeto, cuya función y significado lógicamente dependerán del lugar en que se encuentre: un carácter ASCII, un código de una palabra claves, un carácter de control o un dato.
Como en el caso de los caracteres gráficos, el formato empleado es el de BASin: una barra invertida, una almohadilla y el número en decimal (de 0 a 255).
Por ejemplo, para insertar el caracter de borrado (12) dentro de una cadena asignada a una variable, haríamos así: let a$="abc\#12def"
. Y para ahorrar unos octetos de memoria (cinco en este caso) en la asignación de un valor podemos hacer esto: let a=code "\#255"
. Es posible ver ejemplos de uso en el programa BBimport 5.
Posibles mejoras
Entre las ideas consideradas para futuras versiones del formato BBim están las siguientes:
#define
: definir metaetiquetas (hay una versión experimental en BBim2BB, pero el metacomando#vim
es más potente y lo hace innecesario).#ifdef
,#ifundef
y#endif
: incluir un zona de código si ha sido o no definida una metaetiqueta.#speed
y#size
: indicar que la sustitución deexit do
se haga atendiendo a la velocidad de ejecución o al tamaño del programa.exit proc
: salir de un procedimiento (se sustituirá por un salto a la línea del siguienteendproc
).exit do
: salir de un bucledo
(se sustituirá porexit if 1
oexit if sgn pi
, según#speed
o#size
).exit for
: salir de un buclefor
(se sustituirá por un salto a la línea siguiente a la delnext
correspondiente a la variable indicada).
Otra mejora muy importante sería dotar al sistema de la capacidad de manejar varios programas en un solo fichero fuente. Esto facilitaría el trabajo con proyectos complejos como La legionela del pisto. Para lograrlo cada programa podría marcarse por ejemplo con las nuevas palabras clave #defprog
y #endprog
. La renumeración de líneas se haría independientemente en cada programa marcado así, pero todos se exportarían en una misma falsa imagen de disquete. La importación grabaría cada programa aparte con su nombre.
Descargas
- betabasic.vim (8.86 KiB): Fichero de resaltado de sintaxis de Vim para Beta BASIC.
- bbim.vim (3.66 KiB): Fichero de resaltado de sintaxis de Vim para el formato BBim de Beta BASIC.
- bbim2bb.vim (17.20 KiB): Programa escrito en Vim para convertir al formato estándar de Beta BASIC un código fuente de formato BBim.
- bbimport.mgt.gz (95.08 KiB): Programa para importar en el intérprete de Beta BASIC un código fuente creado en el sistema anfitrión del emulador de ZX Spectrum. Imagen de disquete MGT comprimida con gzip (en la página de BBimport está detallado el contenido del disquete).
- bbimport.mgt.zip (94.60 KiB): El mismo fichero anterior pero comprimido con zip.
- bbimport_5.bbim (3.52 KiB): Código fuente de BBimport 5 en el formato BBim original.