SBim

Descripción del contenido de la página

Preprocesador para S*BASIC

Etiquetas:

«SBim» significa «S*BASIC improved», esto es, «S*BASIC mejorado». «S*BASIC» quiere decir tanto SuperBASIC (el BASIC original de Sinclair QL) como su versión mejorada SBASIC.

SBim es por una parte un formato mejorado para escribir código en S*BASIC; por otra, es un preprocesader escrito en Vim que traduce el código fuente al formato propio de S*BASIC, listo para ser interpretado.

El formato SBim

Mejoras que aporta el formato SBim respecto al S*BASIC original:

Comentarios

En SBim puede usarse las comillas simples para los comentarios de línea, como es habitual en otras versiones de BASIC. Estos comentarios serán eliminados durante la conversión del código a S*BASIC.

Estos comentarios pueden estar al inicio de la línea (precedidos opcionalmente por espacios o tabuladores), siempre que estén seguidos por un espacio (o nada). Si no están al inicio de la línea deben estar precedidos por un espacio y seguidos por otro espacio (o nada).

Por supuesto, los comentarios de línea propios de S*BASIC, con rem o REMark, pueden seguir usándose y serán conservados.

Líneas partidas

Una línea de código fuente puede ser dividida en más de una línea de texto. SBim usa una barra inclinada hacia la izquierda («\»), como es habitual en diversos lenguajes de programación.

En S*BASIC «\» es un separador de impresión que en ocasiones puede quedar al final de la línea de código. Para evitar la ambigüedad en dichos casos se puede añadir el separador de instrucciones, los dos puntos («:»).

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, en que también se ilustra el uso original de «\» como operador de impresión:

let \
  d=18871215
print\
  "Saluton, \
  mondo!":\
list
print\ \
  "Bonan matenon"
print\:
clear

El código anterior convertido a S*BASIC:

1 let d=18871215
2 print "Saluton, mondo!":list
3 print\"Bonan matenon"
4 print\:
5 clear

Etiquetas

En SBim se usan etiquetas en lugar de números de línea.

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 código ASCII, 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 @routine1
stop

@routine1
  print "Routine 1"
  @wait
  if not rnd then goto @wait
  return

Para mayor claridad, puede usarse el comando label para definir las etiquetas:

gosub @routine1
stop

label @routine1
  print "Routine 1"
  label @wait
  if not rnd then goto @wait
  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:

restore @my_data+index

Sin embargo eso puede tener efectos indeseados. Por ejemplo, dado el siguiente código:

label @blabla
print "Hola"
print "Mi correo-e es: superbasic@blablabla.info"
print "Y mi otro correo-e es: superbasic@blabla.info"

El resultado final en S*BASIC sería el siguiente, con una sustitución indeseada en la última línea:

2 print "Hola"
3 print "Mi correo-e es: superbasic@blablabla.info"
4 print "Y mi otro correo-e es: superbasic1.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: superbasic";chr$(64);"blabla.info"
rem Arroba separada:
print "Y mi otro correo-e es: superbasic@";"blabla.info"

Primer número de línea

Puede definirse el primer número de línea que se usará para renumerar el programa final, con el comando #firstline, que debe estar al inicio de cualquier línea del programa (los espacios o tabuladores previos no serán tenidos en cuenta):

#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.

Inclusión de otros ficheros fuente

Es posible incluir otros ficheros fuente dentro del principal con la directiva #include:

#include lib/routine.bas

A su vez, el fichero incluido puede contener otras directivas #include.

Metaetiquetas y conversión condicional

Ejemplo
#define debugging
#define qdos

#ifdef debugging
  print "I'm debugging"
#endif

#ifdef qdos

  ' QDOS version

#else

  ' SMSQ/E version

#endif


Posibles mejoras

Entre las ideas consideradas para futuras versiones del formato SBim están las siguientes:

Instalación

Para instalar SBim basta ejecutar make install en el directorio del programa. Los ficheros propios de Vim se instalarán en <~/.vim>, pero el comando sbim se copiará en <~/bin>. Si se desea usar en su lugar, hay que editar el valor de la variable BINDIR en el fichero . Para desinstalar, make uninstall.

Uso

Cuando se usa el editor Vim para editar ficheros con extensión «.sbim», o ficheros que incluyen una línea de configuración de Vim con el comando filetype=sbim, estará disponible el atajo de teclado _bas para convertir el código en formato estándar de S*BASIC. El resultado será un fichero con el mismo nombre que el actual y en su mismo directorio, pero con la extensión _bas añadida.

SBim puede usarse también como un comando, en cuyo caso puede indicarse el nombre del fichero de salida. Ejemplos:

sbim inputfile.bas
sbim inputfile.bas outputfile.bas

Código fuente

El fichero principal de SBim es el conversor de código:

" sbim.converter.vim
" (~/.vim/sbim.vim)

" This file is part of SBim
" http://programandala.net/es.programa.sbim.html

" Last modified 201709291146
" See change log at the end of the file

" ==============================================================
" Description

" This VimL program converts S*BASIC source code written in the
" SBim format to an ordinary S*BASIC file ready to be loaded by
" a S*BASIC interpreter.

" ==============================================================
" Author and license

" Author: Marcos Cruz (programandala.net), 2011, 2012, 2015,
" 2016, 2017

" You may do whatever you want with this work, so long as you
" retain the copyright/authorship/acknowledgment/credit
" notice(s) and this license in all redistributed copies and
" derived works.  There is no warranty.

" ==============================================================

if exists("*SBim")
  " Function `SBim` is already defined.
  finish
endif

" ==============================================================
" Generic functions {{{1

function! Trim(input_string)
  " Remove trailing spaces from a string.
  " Reference:
  " http://stackoverflow.com/questions/4478891/is-there-a-vimscript-equivalent-for-rubys-strip-strip-leading-and-trailing-s
  return substitute(a:input_string, '^\s*\(.\{-}\)\s*$', '\1', '')
endfunction

" ==============================================================
" Cleaning {{{1

function! SBimClean()

  silent %s,\t\+, ,ge " Remove tabs
  echo 'Tabs removed.'

  silent %s,\(^\s*\|\s\+\)'\(\s.*\)\?$,,e " Remove line comments
  echo 'Comments removed.'

  silent %s,^\s*\n,,ge " Remove the empty lines
  echo 'Empty lines removed.'

  silent %s,^\s*\(.\+\)\s*$,\1,e " Remove blanks
  echo 'Indentation and blanks removed.'

  silent %s,\\\s*\n,,e " Join the splitted lines 
  echo 'Splitted lines joined.'

endfunction

" ==============================================================
" Renum

function! SBimRenum()

  " Put line numbers;
  " remove spaces from blank lines;
  " save the file.

  " Call the the nl program (part of the Debian coreutils package):
  execute ":silent %!nl --body-numbering=t --number-format=rn --number-width=5 --number-separator=' ' --starting-line-number=".s:firstLine." --line-increment=1"

  " In older versions of coreutils,
  " -v sets the first line number, and -i sets the line increment.
  " (the long option for -v doesn't work, though the manual mentions it).
  " Modern versions of nl uses the clearer options
  " --first-line and --line-increment, see:
  " http://www.gnu.org/software/coreutils/manual/coreutils.html#nl-invocation

  " Remove all spaces from lines that only contain spaces:
  ":%s/^\s\+$//

  " Remove spaces before line numbers
  "(nl has no option to remove them):
  silent %substitute/^\s*//e

  echo 'Line numbers added.'

endfunction

function! SBimGetFirstLine()

  " Store into s:firstLine the first line number
  " to be used by the final S*BASIC program
  " The command #firstline can be used to set
  " the desired line number. Only the first occurence
  " of #firstline will be used; it can be anywhere
  " in the source but always at the start of a line
  " (with optional indentation).

  let s:firstLine=1 " default value

  " Go to the top of the file:
  normal gg
  if search('^\s*#firstline\s\+[0-9]\+\>','Wc')
    " Store the number into register 'l':
    normal ww"lyw
    " And then into the variable:
    let s:firstLine=getreg('l',1)
  endif
  echo 'First line number: '.s:firstLine

endfunction

" ==============================================================
" #include {{{1

function! SBimInclude()

  " Execute all '#include' directives.

  " Syntax:
  " #include filename

  " Warning: nested including is possible, but no recursion check is made!

  call cursor(1,1) " Go to the top of the file.
  let l:includedFiles=0 " Counter
  while search('^\s*#include\s\+','Wc')
    let l:includedFiles += 1
    let l:filename=matchstr(getline('.'),'\S\+.*',8)
    call setline('.',"' <<< start of included file ".l:filename)
    call append('.',"' >>> end of included file ".l:filename)
    let l:filecontent=readfile(s:sourceFileDir.'/'.l:filename)
    call append('.',l:filecontent)
  endwhile

  if l:includedFiles==0
    echo 'No file included'
  elseif l:includedFiles==1
    echo 'One file included'
  else
    echo l:includedFiles 'files included'
  endif

endfunction

" ==============================================================

Descargas

También se puede descargar la última versión 2.0.0 en desarrollo de SBim en GitHub.

Páginas relacionadas

SuperBASIC Vim syntax file
Fichero de Vim para colorear código en SuperBASIC o SBASIC.
MBim
Utilería para desarrollo cruzado en MasterBASIC con SimCoupe.
BBim
Utilería para escribir programas para ZX Spectrum en BBim (formato mejorado de Beta BASIC) con el editor Vim.

Enlaces externos relacionados