BaCon: transpřekladač z jazyka BASIC do jazyka C

6. 12. 2022
Doba čtení: 39 minut

Sdílet

Programátor Autor: Depositphotos
Programátor
Představíme si možnosti poskytované nástrojem BaCon. Jde o transpřekladač jazyka BASIC (resp. jeho rozšířené podoby) do jazyka C. Tento nástroj je zajímavý proto, že umožňuje prostudovat různé aspekty a problémy transpřekladu.

Obsah

1. BaCon: transpřekladač BASICu do C

2. Překlad BaConu

3. „Hello world“ v BaConu

4. Struktura programů vytvořených v BaConu

5. Čísla řádků v původním zdrojovém kódu BASICu

6. Základní operace s poli

7. Dvourozměrná pole

8. Příkaz GOTO a LABEL

9. Podprogramy založené na příkazech GOSUBRETURN

10. Struktura programové smyčky typu WHILE-WEND

11. Struktura programové smyčky FOR se záporným krokem

12. Vnořené programové smyčky a manipulace s polem – bubble sort

13. Využití maker preprocesoru jazyka C: zápis příkazů malými písmeny

14. Operace s asociativními poli

15. Operace se záznamy

16. Pole záznamů

17. Závěrečné zhodnocení

18. Repositář s demonstračními příklady

19. Dřívější články o interpretrech a překladačích programovacího jazyka BASIC

20. Odkazy na Internetu

1. BaCon: transpřekladač BASICu do C

Na stránkách Roota jsme se již několikrát zabývali programovacím jazykem BASIC, a to jak jeho dnes již zastaralými „retro“ interpretry pocházejícími většinou z první poloviny osmdesátých let minulého století, tak i některými novějšími reinkarnacemi tohoto jazyka (odkazy na tyto články jsou uvedeny v devatenácté kapitole). Současně jsme si již mnohokrát ukázali možnosti nabízené některými transpilery, tj. překladači, které negenerují přímo strojový kód či bajtkód pro nějaký virtuální stroj (JVM, Python VM atd.), ale transformují zdrojový kód z jednoho programovacího jazyka do jazyka jiného. To s sebou přináší mnohé problémy, které mohou být způsobeny rozdílným typovým systémem, zcela odlišnou sémantikou obou jazyků, ztrátou informací o souborech a řádcích v původním zdrojovém kódu, menší čitelnost transpilovaného kódu atd. Ovšem mnohdy výhody převažují – přenositelnost na všechny platformy podporované cílovým jazykem, není nutné vytvářet optimalizující překladač, návaznost na existující ekosystém atd.

Obrázek 1: Nové (tedy alespoň relativně) vydání BBC BASICu, který již oslavil čtyřicet let od svého vzniku.

V podobě BaConu se obě výše uvedené technologie spojily, protože BaCon je transpřekladačem BASICu do jazyka C. Potenciální možnosti cílové platformy (C běží prakticky na jakémkoli typu mikrořadiče i mikroprocesoru) se tak spojují s možnostmi BASICu. Ty jsou však, jak uvidíme v dalších kapitolách, z dnešního pohledu již poněkud omezené a netypické, takže cílová skupina uživatelů je (podle názoru autora článku) relativně malá.

Obrázek 2: Kombinace zdrojového kódu v BBC BASICu s assemblerem. Podobný koncept byl podporován i v Turbo Pascalu i mnoha variantách programovacího jazyka C.

Poznámka: BaCon není v žádném případě jediným transpřekladačem generujícím zdrojový kód v jazyku C. Takových transpřekladačů vzniklo za celou dobu existence céčka mnoho desítek a možná i stovek; ostatně i proto se programovacímu jazyku C někdy říká „univerzální assembler“.

Obrázek 3: Program zapsaný v AppleSoft BASICu spuštěný na počítači Apple II.

2. Překlad BaConu

Všechny další kapitoly ukazují možnosti BaConu na několika demonstračních příkladech. Abychom mohli tyto příklady (trans)přeložit, je pochopitelně nutné mít k dispozici vlastní transpřekladač. Jeho zdrojové kódy lze získat z adresy http://basic-converter.org/#downloads. Po stažení a rozbalení archivu se překlad spustí příkazem:

$ make bacon

S průběhem:

rm -f build/* build-cpp/*
Converting 'bacon.bac'... done, 9872 lines were processed in 189 seconds.
Creating lexical analyzer... done.
Compiling 'bacon.bac'... make[1]: Entering directory '/home/ptisnovs/temp/bacon_trunk/build'
gcc  -g -O2 -fno-var-tracking-assignments -c bacon.bac.c
gcc -o bacon bacon.bac.o    -lm
make[1]: Leaving directory '/home/ptisnovs/temp/bacon_trunk/build'
Done, program 'bacon' ready.
strip build/bacon
Skipping BaConGUI for GTK.
Skipping BaConGUI for FLTK.
Run 'make install' or 'sudo make install' to install BaCon on your system.

Výsledkem bude nový spustitelný soubor bacon umístěný v podadresáři build.

Poznámka: alternativně je možné při překladu specifikovat, že se má přidat podpora pro grafická uživatelská rozhraní GTK nebo pro FLTK. Pro tyto účely se používají příkazy:
$ make bacongui-gtk
$ make bacongui-fltk

3. „Hello world“ v BaConu

Možnosti a některá omezení BaConu si ukážeme na několika demonstračních příkladech. Začneme pochopitelně naprostou klasikou, tedy programem typu „Hello world“, který lze v BaConu (a jakémkoli jiném BASICu vhodném toho jména) zapsat příkazem PRINT. Příkazy REM pouze uvozují poznámky:

REM *****************************
REM
REM Program "Hello world"
REM
REM Uprava pro BaCon
REM
REM *****************************
 
PRINT "Hello, world!"

Alternativně lze REM nahradit za apostrof:

' *****************************
'
' Program "Hello world"
'
' Uprava pro BaCon
'
' *****************************
 
PRINT "Hello, world!"
Poznámka: všechna klíčová slova BASICu, zde konkrétně slova REM a PRINT, je nutné psát velkými písmeny. Tím se – kromě dalších věcí – zajistí, že nedojde ke kolizím s podobnými klíčovými slovy v jazyku C (rozdíl mezi IF a if atd.). Podrobnosti si řekneme v navazujících kapitolách; stejně tak si ukážeme techniku, jak se této vlastnosti zbavit.

4. Struktura programů vytvořených v BaConu

Překlad, resp. přesněji řečeno transpřeklad, se provede příkazem:

$ ./bacon hello.bac

přičemž je nutné, aby zdrojové kódy měly příponu .bac (což lze snadno upravit zásahem do zdrojových kódů BaConu). Výsledkem by měl být spustitelný soubor. Pokud však chcete vidět, jak vypadá kód transpilovaný do C, použijte příkaz:

$ ./bacon -p hello.bac

Výsledkem bude několik souborů, které ukazují, že se vlastně vytvoří plnohodnotný C projekt s vlastním Makefile:

-rwxrwxr-x 1 ptisnovs ptisnovs  33888 Nov 30 15:10 hello
-rw-rw-r-- 1 ptisnovs ptisnovs    153 Nov 27 08:53 hello.bac
-rw-rw-r-- 1 ptisnovs ptisnovs   1337 Nov 30 15:10 hello.bac.c
-rw-rw-r-- 1 ptisnovs ptisnovs     39 Nov 30 15:10 hello.bac.float.h
-rw-rw-r-- 1 ptisnovs ptisnovs  13654 Nov 30 15:10 hello.bac.functions.h
-rw-rw-r-- 1 ptisnovs ptisnovs  30376 Nov 30 15:10 hello.bac.generic.h
-rw-rw-r-- 1 ptisnovs ptisnovs    292 Nov 30 15:10 hello.bac.h
-rw-rw-r-- 1 ptisnovs ptisnovs   6324 Nov 30 15:10 hello.bac.lex
-rw-rw-r-- 1 ptisnovs ptisnovs  76909 Nov 30 15:10 hello.bac.lex.c
-rwxrwxr-x 1 ptisnovs ptisnovs  40176 Nov 30 15:10 hello.bac.lex.exe
-rw-rw-r-- 1 ptisnovs ptisnovs      0 Nov 30 15:10 hello.bac.log
-rw-rw-r-- 1 ptisnovs ptisnovs  26096 Nov 30 15:10 hello.bac.o
-rw-rw-r-- 1 ptisnovs ptisnovs     38 Nov 30 15:10 hello.bac.string.h
-rw-rw-r-- 1 ptisnovs ptisnovs    229 Nov 30 15:10 Makefile.bacon
Poznámka: nelekejte se souborů hello.bac.lex.exe atd.; jedná se pouze o pojmenování kompatibilní s Windows.

Hlavičkový soubor hello.bac.h neobsahuje (prozatím) žádné důležité deklarace:

/* Created with BaCon 4.4.1 - (c) Peter van Eerten - MIT License */
#include "hello.bac.generic.h"
#include "hello.bac.functions.h"
#line 1 "hello.bac"
#line 2 "hello.bac"
#line 3 "hello.bac"
#line 4 "hello.bac"
#line 5 "hello.bac"
#line 6 "hello.bac"
#line 7 "hello.bac"
#line 9 "hello.bac"

Naproti tomu hello.bac.c obsahuje implementaci funkce main s kódem pro inicializaci (my ho vlastně nepoužijeme) a taktéž strojově přeložený příkaz PRINT do podoby s řetězcovým literálem:

__b2c__assign = (char *) "Hello, world!";
if (__b2c__assign != NULL)
{
        fputs (__b2c__assign, stdout);
}

Podívejme se na celý soubor hello.bac.c:

/* Created with BaCon 4.4.1 - (c) Peter van Eerten - MIT License */
#include "hello.bac.h"
#include "hello.bac.string.h"
#include "hello.bac.float.h"
/****************************/
/* Main program starts here */
/****************************/
int main (int argc, char **argv)
{
        setvbuf (stdout, NULL, _IOLBF, 0);
        if (argc > 0)
        {
                __b2c__me_var__b2c__string_var = strdup (argv[0]);
        }
        if (argc == 2 && !strcmp (argv[1], "-bacon"))
        {
                fprintf (stderr, "Converted by %s.\n", COMPILED_BY_WHICH_BACON__b2c__string_var);
                exit (EXIT_SUCCESS);
        }
/* Setup the reserved variable 'ARGUMENT' */
        __b2c__argument (&ARGUMENT__b2c__string_var, argc, argv);
/* By default seed random generator */
        srandom ((unsigned int) time (NULL));
/* Determine current moment and keep it for timer function */
        __b2c__timer (1);
/* Setup error signal handling */
        signal (SIGILL, __b2c__catch_signal);
        signal (SIGABRT, __b2c__catch_signal);
        signal (SIGFPE, __b2c__catch_signal);
        signal (SIGSEGV, __b2c__catch_signal);
/* Rest of the program */
#line 1 "hello.bac"
#line 2 "hello.bac"
#line 3 "hello.bac"
#line 4 "hello.bac"
#line 5 "hello.bac"
#line 6 "hello.bac"
#line 7 "hello.bac"
#line 9 "hello.bac"
        __b2c__assign = (char *) "Hello, world!";
        if (__b2c__assign != NULL)
        {
                fputs (__b2c__assign, stdout);
        }
        fputs ("\n", stdout);
        return (0);
}

5. Čísla řádků v původním zdrojovém kódu BASICu

V céčkovém kódu vygenerovaném BaConem jste si mohli povšimnout několika direktiv ve tvaru:

#line 1 "hello.bac"

Tyto direktivy informují překladač o tom, jakým způsobem má uživatele informovat o případných chybách, ke kterým může během překladu dojít (a dochází, jak ostatně uvidíme dále). Uživatele totiž většinou nezajímá to, že chyba nastala v souboru hello.bac.c, který je vygenerován; zajímá ho, že se chyba týká například třetího řádku ze vstupního souboru hello.bac.

Poznámka: jedná se o velmi dobrou a přitom často přehlíženou vlastnost programovacího jazyka C. V ostatních programovacích jazycích je (někdy) možné podobné funkcionality dosáhnou využitím source map.

6. Základní operace s poli

Už v originálním BASICu bylo možné pracovat s jednorozměrnými poli, která mohla obsahovat číselné hodnoty (původně jen reálná čísla, později se rozlišovalo mezi reálnými a celými čísly). Pole se definovala a současně i alokovala příkazem DIM a některé BASICy umožňovaly dokonce realokaci pole příkazem REDIM. V BaConu se pole definuje a alokuje odlišně – zadáním názvu pole a počtu prvků. Před tuto deklaraci se většinou ještě zadává klíčové slovo LOCAL znamenající, že pole bude vytvořeno lokální v rámci funkce main (nebo subrutiny, kde je pole definováno). K přístupu k prvkům pole se používají hranaté závorky (jako v C, Javě, atd.) a nikoli závorky kulaté, jako v klasickém BASICu:

REM *****************************
REM 
REM Prace s jednorozmernymi poli
REM 
REM Uprava pro BaCon
REM 
REM *****************************
 
LOCAL A[10]
 
FOR I=0 TO 10
    A[I]=10*I
NEXT I
 
REM TISK POLE
FOR I=0 TO 10
    PRINT A[I]
NEXT I

Po překladu se ve vygenerovaném hlavičkovém souboru objeví definice, deklarace a současně i inicializace pole:

...
...
...
long A[(uint64_t) 10 + 0] = { 0 };
...
...
...
long I;
...
...
...

Samotná práce s poli se přeloží do prakticky totožného kódu jako v BaConu:

...
...
...
for (I = 0; I <= 10; I += 1)
{
        A[(uint64_t) I] = (long) (10 * I);
}
for (I = 0; I <= 10; I += 1)
{
        fputs (STR__b2c__string_var (A[(uint64_t) I]), stdout);
        fputs ("\n", stdout);
}
return (0);
Poznámka: ve skutečnosti je v programu logická chyba, protože prvky pole jsou indexovány od nuly a počet prvků je roven deseti, takže by se programová smyčka měla ukončit hodnotou 9. Na tuto chybu nás však BaCon neupozorní a ani v runtime na ni nemusí být snadné přijít (na rozdíl od originálního BASICu, který tyto věci hlídá).

7. Dvourozměrná pole

Podobným způsobem jako s jednorozměrnými poli se v BaConu pracuje s poli dvourozměrnými, samozřejmě s tím dodatkem, že si opět musíme dát pozor na rozměry pole a vztah mezi rozměrem pole a koncovou hodnotou počitadel v programové smyčce. V dalším demonstračním příkladu se pracuje s polem s 6×6 prvky:

REM *****************************
REM 
REM Prace s dvourozmernymi poli
REM 
REM Uprava pro BaCon
REM 
REM *****************************
 
LOCAL M[6][6]
 
FOR I=0 TO 5
    FOR J=0 TO 5
        M[I][J]=I*J
    NEXT J
NEXT I
 
REM TISK POLE
FOR I=0 TO 5
    FOR J=0 TO 5
        PRINT M[I][J], " ";
        NEXT J
    PRINT
NEXT I
Poznámka: povšimněte si středníku v příkazu PRINT, jenž umožňuje tisk většího množství zpráv na jediné řádce. Tento koncept je převzat z originálního BASICu (ovšem například podobně použitá čárka, která by měla umožnit zarovnání na další tabulační zarážku, již není plně zpětně kompatibilní).

Definice a inicializace dvourozměrného pole v transpřeloženém céčku vypadá takto:

long M[(uint64_t) 6 + 0][(uint64_t) 6 + 0] = { 0 };
 
long I;
 
long J;

Práce s polem v céčkovém programu prakticky přesně odpovídá BASICovému protějšku (pokud zanedbáme neustálé testy, zda byl program přerušen uživatelem):

for (I = 0; I <= 5; I += 1)
{
        for (J = 0; J <= 5; J += 1)
        {
                M[(uint64_t) I][(uint64_t) J] = (long) (I * J);
        }
        if (__b2c__break_ctr)
        {
                __b2c__break_ctr--;
                if (!__b2c__break_ctr)
                {
                        if (__b2c__break_flag == 1)
                                break;
                        else
                                continue;
                }
                else
                        break;
        }
}
for (I = 0; I <= 5; I += 1)
{
        for (J = 0; J <= 5; J += 1)
        {
                fputs (STR__b2c__string_var (M[(uint64_t) I][(uint64_t) J]), stdout);
                __b2c__assign = (char *) " ";
                if (__b2c__assign != NULL)
                {
                        fputs (__b2c__assign, stdout);
                }
                fflush (stdout);
        }
        if (__b2c__break_ctr)
        {
                __b2c__break_ctr--;
                if (!__b2c__break_ctr)
                {
                        if (__b2c__break_flag == 1)
                                break;
                        else
                                continue;
                }
                else
                        break;
        }
        fputs ("\n", stdout);
}
return (0);
Poznámka: v kódu je jasně patrné neustálé vkládání testu na přerušení běhu programu uživatelem (Ctrl+Break), což je operace, kterou klasické BASICy plně podporovaly.

8. Příkaz GOTO a LABEL

Klasické BASICy kromě programové smyčky FOR-NEXT obsahovaly i podporu pro skoky na čísla řádků. Pro tento účel se používal příkaz GOTO a všechny řádky programu byly očíslovány, viz následující příklad:

1 REM *****************************
2 REM Vypocet nejvetsiho spolecneho
3 REM delitele.
4 REM
5 REM Uprava pro Atari BASIC
6 REM
7 REM *****************************
8 REM
9 REM
10 PRINT "X=";
20 INPUT X
30 PRINT "Y=";
40 INPUT Y
50 IF X=Y THEN PRINT "GCD: ";X:END
60 IF X>Y THEN X=X-Y:GOTO 50
70 IF X<Y THEN Y=Y-X:GOTO 50
998 REM finito
999 STOP

V BaConu se čísla řádků nepoužívají, ovšem příkaz GOTO je stále podporován (jinak by se ani nejednalo o BASIC :-). Cíl skoku je pojmenován příkazem LABEL. Předchozí příklad by se do BaConu mohl převzat následujícím způsobem:

REM *****************************
REM 
REM Vypocet nejvetsiho spolecneho
REM delitele.
REM 
REM Uprava pro BaCon
REM 
REM *****************************
 
PRINT "X=";
INPUT X
PRINT "Y=";
INPUT Y
 
LABEL LOOP
 
IF X=Y THEN
    PRINT "GCD: ";X
    STOP
END IF
 
IF X>Y THEN
    X=X-Y
    GOTO LOOP
END IF
 
IF X<Y THEN
     Y=Y-X
     GOTO LOOP
END IF

Po překladu do jazyka C se taktéž použije příkaz goto, který tento jazyk (plně) podporuje, podobně jako odkazy na cíle skoků (labels). Viz též zvýrazněné řádky:

...
...
...
__b2c__input (&__b2c__assign, "\n");
X = atol (__b2c__assign);
free (__b2c__assign);
__b2c__assign = NULL;
__b2c__assign = (char *) "Y=";
if (__b2c__assign != NULL)
{
        fputs (__b2c__assign, stdout);
}
fflush (stdout);
__b2c__input (&__b2c__assign, "\n");
Y = atol (__b2c__assign);
free (__b2c__assign);
__b2c__assign = NULL;
LOOP:
;
__b2c__label_floatarray_LOOP = 0;
__b2c__label_stringarray_LOOP = 0;
if ((X) == Y)
{
        __b2c__assign = (char *) "GCD: ";
        if (__b2c__assign != NULL)
        {
                fputs (__b2c__assign, stdout);
        }
        fputs (STR__b2c__string_var (X), stdout);
        fputs ("\n", stdout);
        kill (getpid (), SIGSTOP);
}
if ((X) > Y)
{
        X = (long) (X - Y);
        goto LOOP;
}
if ((X) < Y)
{
        Y = (long) (Y - X);
        goto LOOP;
}
return (0);

9. Podprogramy založené na příkazech GOSUBRETURN

V klasických interpretrech programovacího jazyka BASIC je možné používat podprogramy (subrutiny). Skok do podprogramu je realizován příkazem GOSUB, který provede skok a současně si zapamatuje řádek (přesněji řečeno příkaz), na který se má vrátit. Návrat z podprogramu je realizován příkazem RETURN. Nejprve si ukažme, jak jsou tyto příkazy použity v Atari BASICu, tedy klasickém interpretru tohoto jazyka z éry osmibitových mikropočítačů:

1 REM *****************************
2 REM Vypocet konstanty Pi.
3 REM
4 REM Uprava pro Atari BASIC
5 REM
6 REM *****************************
7 REM
8 REM
9 REM
10 N=1
20 FOR I=1 TO 10
25 GOSUB 1000:REM VYPOCET PI
30 PRINT I,N,PI
35 N=N*2
40 NEXT I
998 REM finito
999 STOP
1000 REM 
1001 REM SUBRUTINA PRO VYPOCET PI
1002 REM
1010 PI=4
1020 FOR J=3 TO N+2 STEP 2
1030 PI=PI*(J-1)/J*(J+1)/J
1040 NEXT J
1050 RETURN 

V BaConu se, jak již víme, čísla řádků nepoužívají. Namísto toho použijeme návěští (label). Upravený zdrojový kód tedy bude vypadat následovně:

REM *****************************
REM 
REM Vypocet konstanty Pi.
REM 
REM Uprava pro BaCon
REM 
REM *****************************
 
LOCAL N=1
 
FOR I=1 TO 10
    REM vypocet PI
    GOSUB PI_COMP
    PRINT "I=",I," N=",N," PI=", PI_VAL
    N=N*2
NEXT I
REM finito
END
 
REM *****************************
REM SUBRUTINA PRO VYPOCET PI
REM *****************************
 
LABEL PI_COMP
PI_VAL = 4.0
FOR J=3 TO N+2 STEP 2
    PI_VAL=PI_VAL*(J-1)/J*(J+1)/J
NEXT J
RETURN 

Zajímavé bude zjistit, jak se vlastně příkazy GOSUB a RETURN přeloží. Zde již není situace tak jednoduchá, jako v případě použití GOTO, které je přímo podporováno i céčkem. U dvojice GOSUB a RETURN je nutné explicitně realizovat zásobník návratových adres (jedná se zde o pole návratových adres); samotné cíle skoků jsou počítány a využívá se zde dvojice (nechvalně známých) funkcí setjmp a longjmp:

for (I = 1; I <= 10; I += 1)
{
        __b2c__gosub_buffer_ptr++;
        if (__b2c__gosub_buffer_ptr >= 64)
        {
                ERROR = 31;
                if (!__b2c__catch_set)
                        RUNTIMEERROR ("GOSUB", 12, "PI.bac", ERROR);
                else if (!setjmp (__b2c__jump))
                        goto __B2C__PROGRAM__EXIT;
        }
        if (!setjmp (__b2c__gosub_buffer[__b2c__gosub_buffer_ptr]))
                goto PI_COMP;
        __b2c__gosub_buffer_ptr--;
        if (__b2c__gosub_buffer_ptr < -1)
                __b2c__gosub_buffer_ptr = -1;
        __b2c__assign = (char *) "I=";
        if (__b2c__assign != NULL)
        {
                fputs (__b2c__assign, stdout);
        }
        fputs (STR__b2c__string_var (I), stdout);
        __b2c__assign = (char *) " N=";
        if (__b2c__assign != NULL)
        {
                fputs (__b2c__assign, stdout);
        }
        fputs (STR__b2c__string_var (N), stdout);
        __b2c__assign = (char *) " PI=";
        if (__b2c__assign != NULL)
        {
                fputs (__b2c__assign, stdout);
        }
        fputs (STR__b2c__string_var (PI_VAL), stdout);
        fputs ("\n", stdout);
        N = (long) (N * 2);
}
exit (EXIT_SUCCESS);
PI_COMP:
;
__b2c__label_floatarray_PI_COMP = 0;
__b2c__label_stringarray_PI_COMP = 0;
PI_VAL = (double) (4.0);
for (J = 3; J <= N + 2; J += 2)
{
        PI_VAL = (double) (PI_VAL * (J - 1) / (double) J * (J + 1) / (double) J);
}
if (__b2c__gosub_buffer_ptr >= 0)
        longjmp (__b2c__gosub_buffer[__b2c__gosub_buffer_ptr], 1);
__B2C__PROGRAM__EXIT:
return (0);
Poznámka: na tomto příkladu je jasně patrné, jak se sémantika BASICu a céčka odlišuje.

10. Struktura programové smyčky typu WHILE-WEND

V mnoha klasických BASICech byl podporován jen jeden typ programové smyčky, a to konkrétně počítané smyčky typu FOR-NEXT. Později byla přidána podpora pro další strukturované příkazy, což mj. znamenalo přidání syntaxe pro programovou smyčku WHILE, jejíž ukončující příkaz se jmenoval WEND. I tento typ smyčky je v BaConu podporován, takže si můžeme upravit program pro výpočet konstanty Pi tak, aby tuto smyčku využíval (a to dokonce dvakrát):

REM *****************************
REM 
REM Výpočet hodnoty konstanty PI
REM postavený na smyčce
REM typu WHILE-WEND.
REM 
REM Uprava pro BaCon
REM *****************************
 
 
N=1
WHILE N<=2000
    GOSUB COMPUTE_PI
    PRINT N," ", PI_VAL
    N=N*2
WEND
 
REM SUBRUTINA PRO VYPOCET PI
LABEL COMPUTE_PI
    PI_VAL=4.0
    J=3
    WHILE J<=N+2
        PI_VAL=PI_VAL*(J-1)/J*(J+1)/J
        J=J+2
    WEND
RETURN

Výše uvedený program se transpřeloží do céčka takovým způsobem, že se využije v céčku „nativní“ programová smyčka while, jejíž sémantika je naprosto totožná s dvojicí WHILE-WEND:

N = (long) (1);
while (N <= 2000)
{
        __b2c__gosub_buffer_ptr++;
        if (__b2c__gosub_buffer_ptr >= 64)
        {
                ERROR = 31;
                if (!__b2c__catch_set)
                        RUNTIMEERROR ("GOSUB", 12, "while_wend_pi.bac", ERROR);
                else if (!setjmp (__b2c__jump))
                        goto __B2C__PROGRAM__EXIT;
        }
        if (!setjmp (__b2c__gosub_buffer[__b2c__gosub_buffer_ptr]))
                goto COMPUTE_PI;
        __b2c__gosub_buffer_ptr--;
        if (__b2c__gosub_buffer_ptr < -1)
                __b2c__gosub_buffer_ptr = -1;
        fputs (STR__b2c__string_var (N), stdout);
        __b2c__assign = (char *) " ";
        if (__b2c__assign != NULL)
        {
                fputs (__b2c__assign, stdout);
        }
        fputs (STR__b2c__string_var (PI_VAL), stdout);
        fputs ("\n", stdout);
        N = (long) (N * 2);
}
COMPUTE_PI:
;
__b2c__label_floatarray_COMPUTE_PI = 0;
__b2c__label_stringarray_COMPUTE_PI = 0;
PI_VAL = (double) (4.0);
J = (long) (3);
while (J <= N + 2)
{
        PI_VAL = (double) (PI_VAL * (J - 1) / (double) J * (J + 1) / (double) J);
        J = (long) (J + 2);
}
if (__b2c__gosub_buffer_ptr >= 0)
        longjmp (__b2c__gosub_buffer[__b2c__gosub_buffer_ptr], 1);
__B2C__PROGRAM__EXIT:
return (0);

11. Struktura programové smyčky FOR se záporným krokem

Vraťme se nyní k programové smyčce, kterou nalezneme v prakticky všech interpretrech programovacího jazyka BASIC (kterých je minimálně několik desítek, ale možná i stovek). V této smyčce je umožněno použít záporný krok, tj. hodnota počitadla je postupně snižována a nikoli zvyšována. Podívejme se opět na jednoduchý demonstrační příklad, konkrétně na výpočet faktoriálu. Programová smyčka se záporným krokem je zde zvýrazněna:

REM *****************************
REM 
REM Vypocet faktorialu
REM 
REM Uprava pro BaCon
REM 
REM *****************************
 
FOR N=0 TO 20
    GOSUB FACTORIAL
    PRINT N," ",FACT
NEXT N
END
 
REM VYPOCET FAKTORIALU
LABEL FACTORIAL
FACT=1
FOR I=N TO 1 STEP -1
    FACT=FACT*I
NEXT I
RETURN

A takto bude vypadat výsledek vygenerovaný transpřekladačem BaConu. Příslušná smyčka se záporným krokem je zvýrazněna:

...
...
...
for (N = 0; N <= 20; N += 1)
{
        __b2c__gosub_buffer_ptr++;
        if (__b2c__gosub_buffer_ptr >= 64)
        {
                ERROR = 31;
                if (!__b2c__catch_set)
                        RUNTIMEERROR ("GOSUB", 10, "factorial.bac", ERROR);
                else if (!setjmp (__b2c__jump))
                        goto __B2C__PROGRAM__EXIT;
        }
        if (!setjmp (__b2c__gosub_buffer[__b2c__gosub_buffer_ptr]))
                goto FACTORIAL;
        __b2c__gosub_buffer_ptr--;
        if (__b2c__gosub_buffer_ptr < -1)
                __b2c__gosub_buffer_ptr = -1;
        fputs (STR__b2c__string_var (N), stdout);
        __b2c__assign = (char *) " ";
        if (__b2c__assign != NULL)
        {
                fputs (__b2c__assign, stdout);
        }
        fputs (STR__b2c__string_var (FACT), stdout);
        fputs ("\n", stdout);
}
exit (EXIT_SUCCESS);
FACTORIAL:
;
__b2c__label_floatarray_FACTORIAL = 0;
__b2c__label_stringarray_FACTORIAL = 0;
FACT = (long) (1);
for (I = N; I >= 1; I += -1)
{
        FACT = (long) (FACT * I);
}
if (__b2c__gosub_buffer_ptr >= 0)
        longjmp (__b2c__gosub_buffer[__b2c__gosub_buffer_ptr], 1);
__B2C__PROGRAM__EXIT:
return (0);

12. Vnořené programové smyčky a manipulace s polem – bubble sort

V dalším demonstračním příkladu je ukázáno použití vnořených programových smyček a taktéž využití „strukturovaného“ příkazu IF, jenž je možné použít společně s programovým blokem. Je tedy nutné nějakým způsobem příkaz IF ukončit, což je zajištěno příkazem END IF (ukončení programové smyčky FOR zajišťuje příkaz NEXT, což již ostatně víme z předchozích kapitol):

REM *****************************
REM 
REM Bubble sort
REM 
REM Uprava pro BaCon
REM 
REM *****************************
 
 
 
GLOBAL A[20]
 
FOR I=0 TO 20
    A[I]=INT(RANDOM(100))
NEXT I
 
GOSUB PRINT_ARRAY
 
FOR I=19 TO 0 STEP -1
    PRINT ".";
    FOR J=0 TO I
        IF A[J]>A[J+1] THEN
            X=A[J]
            A[J]=A[J+1]
            A[J+1]=X
        END IF
    NEXT J
NEXT I
 
PRINT ""
PRINT "SORTED:"
 
GOSUB PRINT_ARRAY
END
 
LABEL PRINT_ARRAY
REM TISK OBSAHU POLE
FOR I=0 TO 20
    PRINT I," ", A[I]
NEXT I
RETURN

Překlad tohoto demonstračního příkladu do jazyka C je poměrně idiomatický, samozřejmě s tím rozdílem, že v céčku se bloky zapisují do složených závorek a tedy není nutné používat klíčová slova pro ukončení bloků:

...
...
...
        for (I = 19; I >= 0; I += -1)
        {
                __b2c__assign = (char *) ".";
                if (__b2c__assign != NULL)
                {
                        fputs (__b2c__assign, stdout);
                }
                fflush (stdout);
                for (J = 0; J <= I; J += 1)
                {
                        if ((A[(uint64_t) J]) > A[(uint64_t) J + 1])
                        {
                                X = (long) (A[(uint64_t) J]);
                                A[(uint64_t) J] = (long) (A[(uint64_t) J + 1]);
                                A[(uint64_t) J + 1] = (long) (X);
                        }
                }
                if (__b2c__break_ctr)
                {
                        __b2c__break_ctr--;
                        if (!__b2c__break_ctr)
                        {
                                if (__b2c__break_flag == 1)
                                        break;
                                else
                                        continue;
                        }
                        else
                                break;
                }
        }
...
...
...

13. Využití maker preprocesoru jazyka C: zápis příkazů malými písmeny

Nyní se dostáváme k zajímavé vlastnosti BaConu, konkrétně k možnosti využití standardních céčkovských maker přímo ve zdrojových kódech BaConu. Tato makra se přímo předávají preprocesoru céčka a BaCon s nimi nijak dál nemanipuluje. K čemu se však tato možnost hodí? Pokud nám nevyhovuje, že se klíčová slova v BaConu zapisují velkými písmeny, můžeme si nadefinovat příslušná makra, jejichž jména jsou zapsána malými písmeny. Vše ilustruje následující zdrojový kód s několika makry, která jsou následně použita namísto původních klíčových slov:

REM *****************************
REM 
REM Bubble sort
REM 
REM Uprava pro BaCon
REM 
REM *****************************
 
#define dim GLOBAL
#define for FOR
#define to TO
#define next NEXT
#define gosub GOSUB
#define return RETURN
#define print PRINT
#define if IF
#define then THEN
#define end END
 
 
dim A[20]
 
for I=0 to 20
    A[I]=INT(RANDOM(100))
next I
 
gosub PRINT_ARRAY
 
for I=19 TO 0 STEP -1
    print ".";
    for J=0 to I
        if A[J]>A[J+1] then
            X=A[J]
            A[J]=A[J+1]
            A[J+1]=X
        end if
    next J
next I
 
print ""
print "SORTED:"
 
gosub PRINT_ARRAY
end
 
LABEL PRINT_ARRAY
REM TISK OBSAHU POLE
for I=0 TO 20
    print I," ", A[I]
next I
return
Poznámka: povšimněte si, že nyní nemá transpřekladač BaConu žádnou možnost kontroly syntaxe ani sémantiky, protože v makrech mohou být uloženy i poměrně rozsáhlé části kódu.

Výsledek transpřekladu, z něhož je patrné, jakým způsobem se makra expandovala:

# 1 "macros.bac"
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
# 1 "macros.bac"
REM *****************************
REM
REM Bubble sort
REM
REM Uprava pro BaCon
REM
REM *****************************
# 21 "macros.bac"
GLOBAL A[20]
 
FOR I=0 TO 20
    A[I]=INT(RANDOM(100))
NEXT I
 
GOSUB PRINT_ARRAY
 
FOR I=19 TO 0 STEP -1
    PRINT ".";
    FOR J=0 TO I
        IF A[J]>A[J+1] THEN
            X=A[J]
            A[J]=A[J+1]
            A[J+1]=X
        END IF
    NEXT J
NEXT I
 
PRINT ""
PRINT "SORTED:"
 
GOSUB PRINT_ARRAY
END
 
LABEL PRINT_ARRAY
REM TISK OBSAHU POLE
FOR I=0 TO 20
    PRINT I," ", A[I]
NEXT I
RETURN

14. Operace s asociativními poli

V BaConu mohou vývojáři nalézt i poměrně „moderní“ prvky. Jedná se například o podporu operací s asociativními poli (slovníky). Prvky uložené do asociativních polí mohou být libovolného typu, ovšem klíče mohou být pouze řetězce – zatímco v moderních programovacích jazycích většinou nejsme nijak omezeni typem klíčů. Asociativní pole je nejdříve nutné deklarovat příkazem:

DECLARE map ASSOC int

kde map je jméno nové proměnné a int je typ prvků uložených ve slovníku. Pro přístup k prvkům se používá syntaxe:

mapa(klíč)

V případě, že se pokusíme o přečtení neexistujícího prvku, vrátí se „nulová hodnota“ daného datového typu (nula pro celá čísla, prázdný řetězec pro řetězce atd.) To je ostatně ukázáno v dalším demonstračním příkladu:

REM *****************************
REM 
REM Operace s asociativnim polem.
REM 
REM Uprava pro BaCon
REM 
REM *****************************
 
DECLARE map ASSOC int
 
map("foo") = 1
map("bar") = 42
map("baz") = -1
 
PRINT map("foo")
PRINT map("bar")
PRINT map("baz")
PRINT map("xyzzy")

V přeloženém programu nalezneme volání funkcí __b2c__…, které interně s asociativními poli pracují:

...
...
...
/* Rest of the program */
__b2c__assoc_map = __b2c__hash_new ();
__b2c__assoc_map_eval = 1;
__b2c__hash_add (__b2c__assoc_map, &__b2c__assoc_map_eval, "foo");
__b2c__assoc_map_eval = 42;
__b2c__hash_add (__b2c__assoc_map, &__b2c__assoc_map_eval, "bar");
__b2c__assoc_map_eval = -1;
__b2c__hash_add (__b2c__assoc_map, &__b2c__assoc_map_eval, "baz");
fputs (STR__b2c__string_var (map ("foo")), stdout);
fputs ("\n", stdout);
fputs (STR__b2c__string_var (map ("bar")), stdout);
fputs ("\n", stdout);
fputs (STR__b2c__string_var (map ("baz")), stdout);
fputs ("\n", stdout);
fputs (STR__b2c__string_var (map ("xyzzy")), stdout);
fputs ("\n", stdout);
return (0);

Další demonstrační příklad ukazuje použití asociativních polí, v nichž jsou uloženy řetězce. Jak je v BASICu zvykem, jsou funkce, proměnné atd. pracující s řetězci ukončeny znakem dolar ($), jenž je součástí názvu dané funkce/proměnné:

REM *****************************
REM 
REM Operace s asociativnim polem.
REM 
REM Uprava pro BaCon
REM 
REM *****************************
 
DECLARE map$ ASSOC STRING
 
map$("foo") = "FOO"
map$("bar") = "BAR"
map$("baz") = ""
 
PRINT map$("foo")
PRINT map$("bar")
PRINT map$("baz")
PRINT map$("xyzzy")

Pro úplnost si ukažme způsob překladu tohoto demonstračního příkladu do céčka. Povšimněte si, že funkce __b2c__hash_??? nyní obsahují koncovku _str, což mimochodem naznačuje další omezení na známé datové typy prvků:

...
...
...
__b2c__assoc_map__b2c__string_var = __b2c__hash_new ();
__b2c__hash_add_str (__b2c__assoc_map__b2c__string_var, "FOO", "foo");
__b2c__hash_add_str (__b2c__assoc_map__b2c__string_var, "BAR", "bar");
__b2c__hash_add_str (__b2c__assoc_map__b2c__string_var, "", "baz");
__b2c__assign = (char *) map__b2c__string_var ("foo");
if (__b2c__assign != NULL)
{
        fputs (__b2c__assign, stdout);
}
fputs ("\n", stdout);
__b2c__assign = (char *) map__b2c__string_var ("bar");
if (__b2c__assign != NULL)
{
        fputs (__b2c__assign, stdout);
}
fputs ("\n", stdout);
__b2c__assign = (char *) map__b2c__string_var ("baz");
if (__b2c__assign != NULL)
{
        fputs (__b2c__assign, stdout);
}
fputs ("\n", stdout);
__b2c__assign = (char *) map__b2c__string_var ("xyzzy");
if (__b2c__assign != NULL)
{
        fputs (__b2c__assign, stdout);
}
fputs ("\n", stdout);
return (0);

15. Operace se záznamy

Kromě asociativních polí je možné v BaConu deklarovat i datový typ záznam (record, struct). Samotná deklarace datového typu a současně i proměnné typu záznam vypadá následovně:

RECORD user
    LOCAL id
    LOCAL name$
    LOCAL surname$
END RECORD

Pro přístup k prvkům se používá dnes již zcela standardní céčková notace:

REM *****************************
REM 
REM Operace se zaznamem.
REM 
REM Uprava pro BaCon
REM 
REM *****************************
 
RECORD user
    LOCAL id
    LOCAL name$
    LOCAL surname$
END RECORD
 
user.id = 42
user.name$ = "Linus"
user.surname$ = "Torvalds"
 
PRINT user.id, " ", user.name$, " ", user.surname$
Poznámka: zde je mimochodem patrné, že čárka se v příkazu PRINT používá poněkud odlišně v porovnání s klasickými BASICy.

Podívejme se nyní na způsob transpřekladu deklarace typu a proměnné typu záznam do programovacího jazyka C. Jedná se o přímočarou transformaci:

typedef struct
{
        long id;
        char *name__b2c__string_var;
        char *surname__b2c__string_var;
} user_TYPE;

Samotné operace se záznamy jsou v céčku opět prakticky stejné, jako v BaConu, takže zde měl transpřekladač poměrně jednoduchou práci:

user.name__b2c__string_var = NULL;
user.surname__b2c__string_var = NULL;
user.id = (long) (42);
user.name__b2c__string_var = __b2c_Swap_String (&user.name__b2c__string_var, "Linus");
user.surname__b2c__string_var = __b2c_Swap_String (&user.surname__b2c__string_var, "Torvalds");
fputs (STR__b2c__string_var (user.id), stdout);
__b2c__assign = (char *) " ";
if (__b2c__assign != NULL)
{
        fputs (__b2c__assign, stdout);
}
__b2c__assign = (char *) user.name__b2c__string_var;
if (__b2c__assign != NULL)
{
        fputs (__b2c__assign, stdout);
}
__b2c__assign = (char *) " ";
if (__b2c__assign != NULL)
{
        fputs (__b2c__assign, stdout);
}
__b2c__assign = (char *) user.surname__b2c__string_var;
if (__b2c__assign != NULL)
{
        fputs (__b2c__assign, stdout);
}
fputs ("\n", stdout);
return (0);

16. Pole záznamů

Kromě jednotlivých záznamů lze v BaConu pracovat i s poli záznamů. Syntaxe pro deklarace takového pole se poněkud liší od deklarace běžných polí:

RECORD users[10]
    LOCAL id
    LOCAL name$
    LOCAL surname$
END RECORD

Z následujícího demonstračního příkladu je patrné, jak se s poli záznamů pracuje:

REM *****************************
REM 
REM Operace se s vice zaznamy.
REM 
REM Uprava pro BaCon
REM 
REM *****************************
 
RECORD users[10]
    LOCAL id
    LOCAL name$
    LOCAL surname$
END RECORD
 
users[0].id = 0
users[0].name$ = "Linus"
users[0].surname$ = "Torvalds"
 
users[1].id = 1
users[1].name$ = "Ken"
users[1].surname$ = "Iverson"
 
users[2].id = 2
users[2].name$ = "Rob"
users[2].surname$ = "Pike"
 
FOR i=0 TO 2
    PRINT users[i].id, " ", users[i].name$, " ", users[i].surname$
NEXT i

Opět se podívejme na způsob transpřekladu předchozího demonstračního příkladu do assembleru. Samotný datový typ „pole záznamů“ vypadá v programovacím jazyku C následovně:

typedef struct
{
        long id;
        char *name__b2c__string_var;
        char *surname__b2c__string_var;
} users_TYPE;
typedef users_TYPE users_type;
users_TYPE users[(uint64_t) 10 + 0] = { 0 };

Následuje výpis části céčkového programu, který vznikl transpřekladem zdrojového kódu v BaConu:

...
...
...
users[(uint64_t) 0].id = (long) (0);
users[(uint64_t) 0].name__b2c__string_var = __b2c_Swap_String (&users[(uint64_t) 0].name__b2c__string_var, "Linus");
users[(uint64_t) 0].surname__b2c__string_var = __b2c_Swap_String (&users[(uint64_t) 0].surname__b2c__string_var, "Torvalds");
users[(uint64_t) 1].id = (long) (1);
users[(uint64_t) 1].name__b2c__string_var = __b2c_Swap_String (&users[(uint64_t) 1].name__b2c__string_var, "Ken");
users[(uint64_t) 1].surname__b2c__string_var = __b2c_Swap_String (&users[(uint64_t) 1].surname__b2c__string_var, "Iverson");
users[(uint64_t) 2].id = (long) (2);
users[(uint64_t) 2].name__b2c__string_var = __b2c_Swap_String (&users[(uint64_t) 2].name__b2c__string_var, "Rob");
users[(uint64_t) 2].surname__b2c__string_var = __b2c_Swap_String (&users[(uint64_t) 2].surname__b2c__string_var, "Pike");
for (i = 0; i <= 2; i += 1)
{
        fputs (STR__b2c__string_var (users[(uint64_t) i].id), stdout);
        __b2c__assign = (char *) " ";
        if (__b2c__assign != NULL)
        {
                fputs (__b2c__assign, stdout);
        }
        __b2c__assign = (char *) users[(uint64_t) i].name__b2c__string_var;
        if (__b2c__assign != NULL)
        {
                fputs (__b2c__assign, stdout);
        }
        __b2c__assign = (char *) " ";
        if (__b2c__assign != NULL)
        {
                fputs (__b2c__assign, stdout);
        }
        __b2c__assign = (char *) users[(uint64_t) i].surname__b2c__string_var;
        if (__b2c__assign != NULL)
        {
                fputs (__b2c__assign, stdout);
        }
        fputs ("\n", stdout);
}
return (0);

17. Závěrečné zhodnocení

V tomto článku jsme se seznámili se základními vlastnostmi transpřekladače BaCon. V mnoha ohledech dokáže tento transpřekladač poměrně slušně „emulovat“ chování klasických BASICů. Najdeme zde však několik rozdílů, a to jak v syntaxi, tak i v chování. Především se nepoužívají čísla řádků (což je většinou dobře), takže musel být vytvořen nový příkaz LABEL umožňující definici pojmenovaných návěští. Výsledek je však čitelnější, než použití čísel řádků, i když se některé původní konstrukce typu ON GOTO a ON GOSUB nemohou používat v původní podobě.

Důležitější je však odlišné chování BaConu v porovnání s klasickými interpretry programovacího jazyka BASIC. Zatímco původní interpretry reagovaly na chybně zadaný příkaz ihned po dokončení aktuálního programového řádku (odeslání řádku RETURNem nebo ENTERem), v BaConu se chyby objeví buď až při transpřekladu nebo dokonce až ve chvíli, kdy je program kompilován překladačem céčka. Kvůli tomuto chování BaCon ztrácí – alespoň podle názoru autora článku – příjemné ovládání s okamžitými zpětnými odpověďmi počítače (i proto byl ostatně BASIC tak oblíben).

18. Repositář s demonstračními příklady

Zdrojové kódy všech popsaných demonstračních příkladů určených pro programovací jazyk BaCon byly uloženy do Git repositáře dostupného na adrese https://github.com/tisnik/8bit-fame. V případě, že nebudete chtít klonovat celý repositář (ten je ovšem stále velmi malý, dnes má velikost zhruba několik desítek kilobajtů), můžete namísto toho použít odkazy na jednotlivé příklady, které naleznete v následující tabulce:

bitcoin školení listopad 24

# Demonstrační příklad Stručný popis příkladu Cesta
1 hello.bas program typu „Hello world“ naprogramovaný v BaConu https://github.com/tisnik/8bit-fame/blob/master/BaCon/hello.bas
2 factorial.bas výpočet faktoriálu https://github.com/tisnik/8bit-fame/blob/master/BaCon/factorial.bas
3 GCD.bas výpočet největšího společného dělitele https://github.com/tisnik/8bit-fame/blob/master/BaCon/GCD.bas
4 1d_array.bas základy práce s 1D polem (vektorem) https://github.com/tisnik/8bit-fame/blob/master/BaCon/1d_array.bas
5 2d_array.bas základy práce s 2D polem (maticí) https://github.com/tisnik/8bit-fame/blob/master/BaCon/2d_array.bas
6 PI.bas výpočet konstanty Pi (standardní BASIC) https://github.com/tisnik/8bit-fame/blob/master/BaCon/PI.bas
7 bubble_sort.bas bublinkové řazení (standardní BASIC) https://github.com/tisnik/8bit-fame/blob/master/BaCon/bubble_sort.bas
8 while_wend_pi.bas výpočet konstanty Pi (BASIC s while/wend) https://github.com/tisnik/8bit-fame/blob/master/BaCon/whi­le_wend_pi.bas
9 macros.bas využití maker preprocesoru https://github.com/tisnik/8bit-fame/blob/master/BaCon/macros.bas
10 macros.pre výsledek preprocesingu souboru macros.bas https://github.com/tisnik/8bit-fame/blob/master/BaCon/macros.pre
11 assoc_array_int.bas základy práce s asociativním polem s prvky typu celé číslo https://github.com/tisnik/8bit-fame/blob/master/BaCon/as­soc_array_int.bas
12 assoc_array_string.bas základy práce s asociativním polem s prvky typu řetězec https://github.com/tisnik/8bit-fame/blob/master/BaCon/as­soc_array_string.bas
13 record.bas operace se záznamem https://github.com/tisnik/8bit-fame/blob/master/BaCon/record.bas
14 records.bas operace s poli záznamů https://github.com/tisnik/8bit-fame/blob/master/BaCon/records.bas

Výsledky transpřekladu do programovacího jazyka C:

# Soubor Stručný popis souboru Cesta
1 1d_array.bac.c výsledek transpřekladu zdrojového souboru 1d_array.bac do C https://github.com/tisnik/8bit-fame/blob/master/BaCon/1d_array.bac.c
2 1d_array.bac.h výsledek transpřekladu zdrojového souboru 1d_array.bac do C https://github.com/tisnik/8bit-fame/blob/master/BaCon/1d_array.bac.h
3 2d_array.bac.c výsledek transpřekladu zdrojového souboru 2d_array.bac do C https://github.com/tisnik/8bit-fame/blob/master/BaCon/2d_array.bac.c
4 2d_array.bac.h výsledek transpřekladu zdrojového souboru 2d_array.bac do C https://github.com/tisnik/8bit-fame/blob/master/BaCon/2d_array.bac.h
5 bubble_sort.bac.c výsledek transpřekladu zdrojového souboru bubble_sort.bac do C https://github.com/tisnik/8bit-fame/blob/master/BaCon/bub­ble_sort.bac.c
6 bubble_sort.bac.h výsledek transpřekladu zdrojového souboru bubble_sort.bac do C https://github.com/tisnik/8bit-fame/blob/master/BaCon/bub­ble_sort.bac.h
7 factorial.bac.c výsledek transpřekladu zdrojového souboru factorial.bac do C https://github.com/tisnik/8bit-fame/blob/master/BaCon/factorial.bac.c
8 factorial.bac.h výsledek transpřekladu zdrojového souboru factorial.bac do C https://github.com/tisnik/8bit-fame/blob/master/BaCon/factorial.bac.h
9 GCD.bac.c výsledek transpřekladu zdrojového souboru GCD.bac do C https://github.com/tisnik/8bit-fame/blob/master/BaCon/GCD.bac.c
10 GCD.bac.h výsledek transpřekladu zdrojového souboru GCD.bac do C https://github.com/tisnik/8bit-fame/blob/master/BaCon/GCD.bac.h
11 hello.bac.c výsledek transpřekladu zdrojového souboru hello.bac do C https://github.com/tisnik/8bit-fame/blob/master/BaCon/hello.bac.c
12 hello.bac.h výsledek transpřekladu zdrojového souboru hello.bac do C https://github.com/tisnik/8bit-fame/blob/master/BaCon/hello.bac.h
13 PI.bac.c výsledek transpřekladu zdrojového souboru PI do C https://github.com/tisnik/8bit-fame/blob/master/BaCon/PI.bac.c
14 PI.bac.h výsledek transpřekladu zdrojového souboru PI do C https://github.com/tisnik/8bit-fame/blob/master/BaCon/PI.bac.h
15 while_wend_pi.bac.c výsledek transpřekladu zdrojového souboru while_wend_pi.bac do C https://github.com/tisnik/8bit-fame/blob/master/BaCon/whi­le_wend_pi.bac.c
16 while_wend_pi.bac.h výsledek transpřekladu zdrojového souboru while_wend_pi.bac do C https://github.com/tisnik/8bit-fame/blob/master/BaCon/whi­le_wend_pi.bac.h
17 macros.bac.c výsledek transpřekladu zdrojového souboru macros.bac do C https://github.com/tisnik/8bit-fame/blob/master/BaCon/macros.bac.c
18 macros.bac.h výsledek transpřekladu zdrojového souboru macros.bac do C https://github.com/tisnik/8bit-fame/blob/master/BaCon/macros.bac.h
19 assoc_array_int.bac.c výsledek transpřekladu zdrojového souboru assoc_array_int.bac do C https://github.com/tisnik/8bit-fame/blob/master/BaCon/as­soc_array_int.bac.c
20 assoc_array_int.bac.h výsledek transpřekladu zdrojového souboru assoc_array_int.bac do C https://github.com/tisnik/8bit-fame/blob/master/BaCon/as­soc_array_int.bac.h
21 assoc_array_string.bac.c výsledek transpřekladu zdrojového souboru assoc_array_string.bac do C https://github.com/tisnik/8bit-fame/blob/master/BaCon/as­soc_array_string.bac.c
22 assoc_array_string.bac.h výsledek transpřekladu zdrojového souboru assoc_array_string.bac do C https://github.com/tisnik/8bit-fame/blob/master/BaCon/as­soc_array_string.bac.h
23 record.bac.c výsledek transpřekladu zdrojového souboru record.bac do C https://github.com/tisnik/8bit-fame/blob/master/BaCon/record.bac.c
24 record.bac.h výsledek transpřekladu zdrojového souboru record.bac do C https://github.com/tisnik/8bit-fame/blob/master/BaCon/record.bac.h
25 records.bac.c výsledek transpřekladu zdrojového souboru records.bac do C https://github.com/tisnik/8bit-fame/blob/master/BaCon/records.bac.c
26 records.bac.h výsledek transpřekladu zdrojového souboru records.bac do C https://github.com/tisnik/8bit-fame/blob/master/BaCon/records.bac.h

19. Dřívější články o interpretrech a překladačích programovacího jazyka BASIC

S programovacím jazykem BASIC, ať již se jedná o zastaralé „retro“ interpretry či o novější reinkarnace tohoto jazyka, jsme se na stránkách Roota již několikrát setkali. Jedná se především o následující články:

  1. Programovací jazyk BASIC na osmibitových mikropočítačích
    https://www.root.cz/clanky/pro­gramovaci-jazyk-basic-na-osmibitovych-mikropocitacich/
  2. Programovací jazyk BASIC na osmibitových mikropočítačích (2)
    https://www.root.cz/clanky/pro­gramovaci-jazyk-basic-na-osmibitovych-mikropocitacich-2/
  3. Programovací jazyk BASIC na osmibitových mikropočítačích (3)
    https://www.root.cz/clanky/pro­gramovaci-jazyk-basic-na-osmibitovych-mikropocitacich-3/
  4. Programovací jazyk BASIC na osmibitových mikropočítačích (dokončení)
    https://www.root.cz/clanky/pro­gramovaci-jazyk-basic-na-osmibitovych-mikropocitacich-dokonceni/
  5. Programovací jazyk BASIC na počítačích kompatibilních s IBM PC
    https://www.root.cz/clanky/pro­gramovaci-jazyk-basic-na-pocitacich-kompatibilnich-s-ibm-pc/
  6. Programovací jazyk BASIC na počítačích kompatibilních s IBM PC v současnosti
    https://www.root.cz/clanky/pro­gramovaci-jazyk-basic-na-pocitacich-kompatibilnich-s-ibm-pc-v-soucasnosti/
  7. PC-BASIC: reinkarnace populárního i zatracovaného GW-BASICu
    https://www.root.cz/clanky/pc-basic-reinkarnace-popularniho-i-zatracovaneho-gw-basicu/
  8. Basic-256: další moderní reinkarnace BASICu určená pro výuku programování
    https://www.root.cz/clanky/basic-256-dalsi-moderni-reinkarnace-basicu-urcena-pro-vyuku-programovani/
  9. BBC BASIC i QBasic oslavují svá kulatá výročí
    https://www.root.cz/clanky/bbc-basic-i-qbasic-oslavuji-sva-kulata-vyroci/
  10. Základy práce s grafickou plochou v jazyku Basic-256
    https://www.root.cz/clanky/zaklady-prace-s-grafickou-plochou-v-jazyku-basic-256/
  11. Small Basic: moderní reinkarnace BASICu určená pro výuku programování
    https://www.root.cz/clanky/small-basic-moderni-reinkarnace-basicu-urcena-pro-vyuku-programovani/
  12. Vestavěné objekty Small Basicu: práce s grafikou, časovačem, reakce na události
    https://www.root.cz/clanky/vestavene-objekty-small-basicu-prace-s-grafikou-casovacem-reakce-na-udalosti/
  13. Programovací jazyk BASIC na herní konzoli Atari 2600
    https://www.root.cz/clanky/pro­gramovaci-jazyk-basic-na-herni-konzoli-atari-2600/
  14. Tvorba her pro Atari 2600 v Batari BASICu: úkol pro hardcode programátory
    https://www.root.cz/clanky/tvorba-her-pro-atari-2600-v-batari-basicu-ukol-pro-hardcode-programatory/
  15. Tvorba her pro Atari 2600 v Batari BASICu: standardní kernel a zvuky
    https://www.root.cz/clanky/tvorba-her-pro-atari-2600-v-batari-basicu-standardni-kernel-a-zvuky/
  16. Tvorba her pro Atari 2600 v Batari BASICu: ovládání čipu TIA
    https://www.root.cz/clanky/tvorba-her-pro-atari-2600-v-batari-basicu-ovladani-cipu-tia/

20. Odkazy na Internetu

  1. Stránka projektu BaCon
    http://basic-converter.org/
  2. Dokumentace BaConu
    http://basic-converter.org/doc_frame.html
  3. Zdrojové kódy i binární obrazy BaConu
    http://basic-converter.org/#downloads
  4. Stránka projektu Basic-256
    https://basic256.org/
  5. So You Want to Learn to Program – BASIC-256 (Third Edition)
    http://syw2l.org/?page_id=407
  6. Why Another BASIC?
    https://basic256.org/2019/06/27/why-another-basic/
  7. Stránka projektu Small Basic
    https://smallbasic-publicwebsite.azurewebsites.net/
  8. List of Programs Made with Small Basic
    https://social.technet.mi­crosoft.com/wiki/contents/ar­ticles/14013.list-of-programs-made-with-small-basic.aspx
  9. Expert to Expert: The Basics of SmallBasic
    https://channel9.msdn.com/blog­s/charles/expert-to-expert-the-basics-of-smallbasic
  10. The Developer’s Reference Guide to Small Basic
    https://social.technet.mi­crosoft.com/wiki/contents/ar­ticles/16767.the-developers-reference-guide-to-small-basic.aspx
  11. Small Basic – Talking to Raspberry Pi
    https://techcommunity.micro­soft.com/t5/small-basic-blog/small-basic-talking-to-raspberry-pi/ba-p/337844
  12. Small Basic – Arduino
    https://techcommunity.micro­soft.com/t5/small-basic-blog/small-basic-arduino/ba-p/337762
  13. Small Basic + micro:bit
    https://techcommunity.micro­soft.com/t5/small-basic-blog/small-basic-micro-bit/ba-p/1968424
  14. #1 Learn Small Basic Programming – Introduction
    https://www.youtube.com/wat­ch?v=e_BaEPCa8OQ
  15. #2 Learn Small Basic Programming – Input, Output & Variables
    https://www.youtube.com/wat­ch?v=VWekYLa33OI
  16. #3 Learn Small Basic Programming – String Concatenation
    https://www.youtube.com/wat­ch?v=iWvIaOaT474
  17. Small Basic – The Programmer's Guide
    https://www.i-programmer.info/programming/other-languages/5196-small-basic-the-programmers-guide.html
  18. Rosetta Code: Category:Microsoft Small Basic
    https://rosettacode.org/wi­ki/Category:Microsoft_Sma­ll_Basic
  19. Fifty Years of BASIC, the Programming Language That Made Computers Personal
    https://time.com/69316/basic/
  20. BBC BASIC i QBasic oslavují svá kulatá výročí
    https://www.root.cz/clanky/bbc-basic-i-qbasic-oslavuji-sva-kulata-vyroci/
  21. GWBASIC User's Manual
    http://www.antonis.de/qbe­books/gwbasman/index2.html
  22. GFA-BASIC
    http://sites.google.com/si­te/gfabasic16/
  23. E-mail od tvůrce GW-Basicu
    http://www.classiccmp.org/pi­permail/cctech/2005-April/042999.html
  24. General Electric GE-400
    http://www.feb-patrimoine.com/PROJET/ge400/ge-400.htm
  25. GE-400 Time-sharing information systems:
    http://www.computerhistory­.org/collections/accession/102646147
  26. A brief history of the development of BASIC (pravděpodobně již nefunkční odkaz)
    http://www.phys.uu.nl/~ber­gmann/history.html
  27. History of BASIC (PDF)
    http://www.q7basic.org/His­tory%20of%20BASIC.pdf
  28. Dartmouth College Computation Center. 1964.-The original Dartmouth BASIC manual
    http://www.bitsavers.org/pdf/dar­tmouth/BASIC_Oct64.pdf
  29. The Original BASIC
    http://www.truebasic.com/
  30. BASIC – Beginners All-purpose Symbolic Instruction Code
    http://hopl.murdoch.edu.au­/showlanguage.prx?exp=176
  31. The History of the Mainframe Computer
    http://www.vikingwaters.com/htmlpa­ges/MFHistory.htm
  32. Dartmouth Time Sharing System
    http://en.wikipedia.org/wi­ki/Dartmouth_Time_Sharing_Sys­tem
  33. General Electric (Wikipedia)
    http://en.wikipedia.org/wi­ki/General_Electric
  34. GE 225 vs. IBM 1401
    http://ed-thelen.org/GE225-IBM1401.html
  35. A GE-225 is found
    http://ed-thelen.org/comp-hist/GE225.html
  36. G.E. 200 Series Computers
    http://www.smecc.org/g_e__200_se­ries_computers.htm
  37. DTSS – Dartmouth Time Sharing System
    http://dtss.dartmouth.edu/index.php
  38. John G. Kemeny: BASIC and DTSS: Everyone a Programmer
    http://dtss.dartmouth.edu/e­veryoneaprogrammer.php
  39. GE-200 series (Wikipedia)
    http://en.wikipedia.org/wiki/GE-200_series
  40. GE-400 series (Wikipedia)
    http://en.wikipedia.org/wiki/GE-400_series
  41. GE-600 series (Wikipedia)
    http://en.wikipedia.org/wiki/GE-600_series
  42. ZX Basic Manual
    http://www.worldofspectrum­.org/ZXBasicManual/
  43. ZX81 BASIC Programming
    http://www.worldofspectrum­.org/ZX81BasicProgramming/
  44. Sinclair BASIC History
    http://scratchpad.wikia.com/wi­ki/Sinclair_BASIC_History
  45. Sinclair BASIC (Wikipedia CZ)
    http://cs.wikipedia.org/wi­ki/Sinclair_BASIC
  46. Sinclair BASIC (Wikipedia EN)
    http://en.wikipedia.org/wi­ki/Sinclair_BASIC
  47. Beta BASIC (Wikipedia EN)
    http://en.wikipedia.org/wi­ki/Beta_BASIC
  48. Beta BASIC (Wikipedia CZ)
    http://cs.wikipedia.org/wi­ki/Beta_BASIC
  49. BETA BASIC NEWSLETTER No 8
    http://spectrum128.ru/hel­p/BetaBasicNewsletter8.pdf
  50. R. T. RUSSELL: The home of BBC BASIC
    http://www.rtrussell.co.uk/
  51. R. T. RUSSELL: A History of BBC BASIC
    http://www.cix.co.uk/~rrus­sell/bbcbasic/history.html
  52. SuperBASIC (Wikipedia EN)
    http://en.wikipedia.org/wi­ki/SuperBASIC
  53. SuperBASIC (Wikipedia CZ)
    http://en.wikipedia.org/wi­ki/SuperBASIC
  54. Laser Basic/Laser Compiler
    http://www.sincuser.f9.co­.uk/049/laser.htm
  55. Laser BASIC (Wikipedia CZ)
    http://cs.wikipedia.org/wi­ki/Laser_BASIC
  56. BBC BASIC
    http://www.bbcbasic.co.uk/bbcba­sic.html
  57. BBC BASIC
    http://mdfs.net/Software/BBCBasic/
  58. BBC BASIC (Z80) for the ZX Spectrum
    http://mdfs.net/Software/BBCBa­sic/Spectrum/
  59. BBC BASIC (Wikipedia CZ)
    http://en.wikipedia.org/wi­ki/BBC_BASIC
  60. BeebWiki – 8-bit Acorn Computer Wiky
    http://beebwiki.jonripley­.com/Main_Page
  61. Porovnání osmibitů
    http://porovnani8bitu.spa­ces.live.com/
  62. Rosetta Code – Main Page
    http://rosettacode.org/wiki/Main_Page
  63. Rosetta Code – Category Basic
    http://rosettacode.org/wi­ki/Category:BASIC
  64. QBasicJedi
    http://www.freewebs.com/qbasicjedi/
  65. QBasic/QuickBasic Downloads
    http://www.freewebs.com/qba­sicjedi/qbdownloads.html
  66. QuickBASIC (Wikipedia CZ)
    http://cs.wikipedia.org/wi­ki/QuickBASIC
  67. QBasic.com
    http://www.qbasic.com/
  68. QBasic (Wikipedia)
    http://cs.wikipedia.org/wiki/QBasic
  69. Dialling with QBASIC
    http://www.mysundial.ca/tsp/qba­sic.html
  70. BASIC (Wikipedia EN)
    http://en.wikipedia.org/wiki/BASIC
  71. BASIC (Wikipedia CZ)
    http://cs.wikipedia.org/wiki/BASIC
  72. Turbo BASIC (Wikipedia CZ)
    http://cs.wikipedia.org/wi­ki/Turbo_BASIC
  73. More BASIC Computer Games
    http://www.atariarchives.or­g/morebasicgames/
  74. How to build an interpreter in Java, Part 1: The BASICs
    http://www.javaworld.com/jw-05–1997/jw-05-indepth.html
  75. Apple I
    http://applemuseum.bott.or­g/sections/computers/a1.html
  76. The Apple 1 history
    http://apple2history.org/his­tory/ah02.html
  77. The Apple 2 history
    http://apple2history.org/his­tory/ah03.html
  78. INTEGER BASIC Reference
    http://www.landsnail.com/a2ref2.htm
  79. APPLESOFT Reference
    http://www.landsnail.com/a2ref.htm
  80. Apple II Programming
    http://home.swbell.net/ru­bywand/csa2pfaq.html
  81. Applesoft Lite: Applesoft BASIC for the Replica-1
    http://cowgod.org/replica1/applesoft/
  82. Simons' BASIC
    http://en.wikipedia.org/wi­ki/Simons'_BASIC
  83. Simon's Basic
    http://www.lemon64.com/?ma­inurl=http%3A//www.lemon64­.com/museum/list.php%3Fli­neoffset%3D54%26genre%3Dma­nualmisc
  84. BASIC
    http://www.c64-wiki.com/index.php/BASIC
  85. C64 Wiki: Simons Basic
    http://www.c64-wiki.de/index.php/Simons_Basic
  86. Simons' Basic (evaluation)
    http://www.atarimagazines­.com/creative/v9n11/60_Si­mons_Basic.php
  87. Bill Gates' Personal Easter Eggs in 8 Bit BASIChttp://www.pagetable.com/?p=43
  88. Kladivo na programy (je tam třeba popsán způsob nahrávání a ochran programů protí kopírování a crackování)
    http://www.grandjihlava.cz/tmp/kla­divo.pdf
  89. Didaktik Gama návod k obsluze
    http://www.grandjihlava.cz/tmp/na­vod.pdf
  90. Můj přítel Didaktik Gama
    http://www.grandjihlava.cz/tmp/pri­teldidaktik.pdf
  91. Tip & trip pro Didaktik
    http://www.grandjihlava.cz/tmp/tip­trikdidaktik.pdf
  92. Muzeum československých mikropočítačů
    http://cs-pocitace.ic.cz/

Autor článku

Vystudoval VUT FIT a v současné době pracuje na projektech vytvářených v jazycích Python a Go.