Ha ezt a nyelvet választod, akkor kezd a programodat a #!bas
sorral.
#!bas
REM globális változók
LET számláló% = 123
LET szám = 3.1415
LET cím% = $0048C
LET sztring$ = "valami"
DIM tömb(10)
REM Induláskor lefuttatandó dolgok
SUB setup
REM lokális változók
LET lokálisvagyok = 123
END SUB
REM Minden képkockánál lefuttatandó dolgok, 60 FPS
SUB loop
REM BASIC stílusú print
PRINT "Épp"; " futok"
REM MEG-4 stílusú kimenet
printf("a számláló %d, balshift %d\n", számláló%, getkey%(KEY_LSHIFT))
END SUB
A BASIC egy mozaikszó, Beginners' All-purpose Symbolic Instruction Code, ami annyit tesz, Kezdők Általános célú Szimbólikus
Utasítás Kódja. Kifejezetten azzal a céllal hozta létre Kemény János 1963-ban, hogy gyerekeket tanítsanak vele programozni. A
MEG-4 BASIC azért ennél kicsit modernebb, tudja a teljes ANSI X3.60-1978 (ECMA-55) szabványt és még jónéhány dolgot az ANSI
X3.113-1987 (ECMA-116) szabványból is, apró eltérésekkel. Az azonosítók hosszabbak lehetnek két karakternél, és a lebegőpontos
valamint integer aritmetikája is 32 bites. A legfontosabb különbségek: nincs interaktív mód, így az utasításokat nem kell
sorszámozni (helyette lehet cimkéket használni), illetve a BASIC kulcsszavak kis-nagybetű érzéketlenek, ahogy azt a specifikáció
elvárja, ellenben a változó és függvénynevek kis-nagybetű érzékenyek. Az összes MEG-4 API függvényhívás kisbetűs; a többit
szabadon választhatod, de azok is kis-nagybetű érzékenyek (például az ALMA
, Alma
és az alma
három különböző változót takar).
Van egy nem szabványos kulcsszava, a DEBUG
, amit akárhová elhelyezhetsz a programodban, és ami meghívja a beépített
[debuggoló]t. Ezt követően lépésről lépésre hajthatod végre a programodat, ellenőrizve, hogy épp mit csinál.
Következzen a részletes leírás példákkal és minden eltérés kiemelve.
A MEG-4 BASIC elfogad tízes számrendszerbeli számokat (akár integer egészszámok, vagy lebegőpontosak, tudományos jelöléssel vagy
annélkül). Hexadecimális számokat a $
karakterrel kell kezdeni (nincs a specifikációban, de így csinálta a Commodore BASIC és
nagyjából az összes többi 80-as évekbeli dialektus is), a sztringeket pedig macskakörömbe kell tenni:
42
3.1415
.123e-10
$0048C
"Viszlát és kösz a halakat!\n"
WARN: A specikiáció szerint 7 bites ASCII-nak kellene lennie, de a MEG-4 BASIC nullával lezárt UTF-8 kódolt sztringeket használ.
Elfogad továbbá C-beli kiemelő kódokat is (például \"
a macskaköröm, \t
a tab, \n
az újsor karakter), és a sztringek
maximális hossza 255 bájtnyi (a specifikáció 18 bájtot vár el).
A változókat nem kell deklarálni, helyette az azonosítójuk utolsó betűje adja meg a típusukat. Ez lehet %
egészszámoknál, $
sztringeknél, és ez nincs a specifikációban, de a MEG-4 BASIC esetében a !
bájtot, a #
pedig duplabájtot jelent (szó). Bármi
más lebegőpontos számot tároló változót eredményez.
LET A% = 42
LET B! = $FF
LET C# = $FFFF
LET D$ = "sztring"
LET E = 3.1415
A konverzió bájt, integer és a lebegőpontos számok között teljesen automatikus. Azonban ha egy sztringet akarsz szám változóba
tenni, vagy szám literált egy sztring változóba, az hibát eredményez (ezekhez használnod kell a STR$
illetve VAL
hívásokat).
Amikor értéket adsz egy változónak, a LET
parancs elhagyható.
Literálok megadhatók még a programodban a DATA
állítások segítségével is, amiket aztán a READ
utasítás rendel változókhoz. A
READ
pontosan annyi adatot olvas be, ahány változó meg lett adva a paramétereként, és többször is hívható. Hogy visszaállítsuk,
hogy a legelső DATA
utasítástól kezdve olvasson a READ
megint, ahhoz a RESTORE
parancsot kell kiadni.
RESTORE
READ név$, jövedelem
DATA "Jóska", 1234
DATA "Pista", 2345
Van pár speciális változó, amiket a rendszer biztosít. Az RND
egy lebegőpontos véletlenszámot ad vissza, 0 és 1 között,
az INKEY$
visszaadja a felhasználó által leütött billentyűt vagy üres sztringet, TIME
a gép bekapcsolása óta eltelt
ezredmásodpercek számát, míg a NOW%
a greenwichi középidő szerinti 1970 január 1.-e éjfél óta eltelt másodperceket adja vissza.
Több, azonos típusú elem rendelhető egyetlen változóhoz, ezeket hívjuk tömböknek.
DIM A(10)
DIM B(10, 10)
DIM C(1 TO 6)
A BASIC specifikáció elvárja a kétdimenziós tömbök kezelését, de a MEG-4 BASIC 4 dimenziót is támogat. A tömb elemei lehetnek bájtok,
egészszámok, lebegőpontos számok vagy sztringek. Dinamikusan nem lehet átméretezni őket a REDIM
-el, minden tömb statikusan lesz
lefoglalva akkorára, amekkora a DIM
-nél meg lett adva. Ha a méret nincs kiírva, akkor egy dimenziót és 10 elemet feltételez.
WARN: Az elemek indexe 1-től indul (mint az ANSI szerint, és nem 0-tól, mint az ECMA-55 szerint). Az OPTION BASE
utasítás
nem támogatott, viszont az induló index átállítható minden tömb esetén a TO
kulcsszóval.
Precedenciájuk szerint csökkenő sorrendben:
**Aritmetikai** ``` ^ * / MOD + - ``` Az első a hatványozás (pl. b a négyzeten `b^2`), aztán szorzás, osztás, a `MOD` pedig a modulus (azaz osztás utáni maradék, pl. `10 MOD 3` az 1), összeadás, kivonás.
**Relációs** ``` <> = <= >= < > ``` Nem egyenlő, egyenlő, kissebb egyenlő, nagyobb egyenlő, kissebb, nagyobb.
**Logikai** ``` NOT AND OR ``` Tagadás (0-ból 1 lesz, minden nem nullából pedig 0), és (csak akkor 1, ha mindkét paramétere nem 0), vagy (legalább az egyik paramétere nem 0).
Van egy nem szabványos operátor, a @
a változó címét adja vissza. Ez akkor használatos, ha valahol a MEG-4 API addr_t
cím
paramétert vár.
Az operátorok a precedenciasorrendjük szerint hajtódnak végre, például a 1+2*3
két operátort tartalmaz, a +
-t és *
-t,
azonban a *
precedenciája magasabb, így először a 2*3
számítódik ki, és csak azután az 1+6
. Ezért a végeredmény 7 és nem 9.
Az END
utasítás leállítja a vezérlést (kilép a programod).
A MEG-4 BASIC nem használ már sorszámokat, helyette cimékkel támogatja a GOTO
parancsot, például:
ez_egy_cimke:
GOTO ez_egy_cimke
WARN: Néhány BASIC dialektus megengedi, hogy több :
-el elválasztott parancsot egy sorba írj. MEG-4 BASIC alatt a :
a cimkét
jelenti, ezért minden parancsot külön sorba kell írni (ahogy azt az ECMA-55 is elvárja).
A feltételes vezérlésátadások szintén cimkéket használnak:
IF a$ <> b$ THEN ez_egy_cimke
ON a GOTO cimke1, cimke2, cimke3 ELSE egyébcimke
Az ON
.. GOTO
mindenképp egy numerikus kifejezést vár, és az annyadik cimkére ugrik, 1-től kezdve (ha a kifejezés nulla
vagy negatív, az mindenképpen az ELSE
ágnak minősül). Nincs ON
.. GOSUB
, mert a GOSUB nem fogad el cimkéket a MEG-4
BASIC-ben.
WARN: A GOSUB
utasítás nem fogad el cimkéket, és kicsit másképp működik MEG-4 BASIC alatt, lásd alább.
Az IF
utasítás elfogad egyaránt numerikus és relációs kifejezést (minden nem nulla eredményt igaznak vesz), sőt mi több, a
többsoros IF
.. THEN
.. ELSE
.. END IF
blokkok is támogatottak (de a SELECT CASE
nem).
IF var >= 0 THEN
PRINT "var értéke pozitív"
ELSE
PRINT "var értéke negatív"
END IF
Kivételként egy parancs lehet az egysoros IF
után, amennyiben az a GOTO
vagy az END
:
IF a < 0 THEN GOTO cimke
IF b > 42 THEN END
Az ismétlő utasítás, a számlálósciklus elöltesztelős (nem futtatja le a blokkot, ha az indulóérték nagyobb (vagy kissebb), mint a határ), és így néz ki:
FOR i = 1 TO 100 STEP 2
...
NEXT i
Ez a FOR
.. NEXT
lényegében pontosan ugyanaz, mint:
LET i = 1
LET lim = 100
LET inc = 2
sor1:
IF (i - lim) * SGN(inc) > 0 THEN sor2
...
LET i = i + inc
GOTO sor1
sor2:
A ciklusváltozónak lebegőpontos típusú változónak kell lennie. A STEP
opcionális (ha nincs megadva, akkor 1.0), utánna a léptetés
lehet egy lebegőpontos literál vagy egy másik lebegőpontos változó. A kiindulási érték és a határ lehet összetettebb kifejezés is,
de azoknak is lebegőpontos számot kell visszaadniuk.
FOR i = (1+2+a)*3 TO 4*(5+6)/b+c STEP j
...
NEXT i
WARN: A specifikációval ellentétben, ami több változót is megenged a NEXT
után, a MEG-4 BASIC csak egyet fogad el. Ezért ha
egymásbaágyazott ciklusaid vannak, akkor több NEXT
parancsot kell használnod, pontosan annyit, mint ahány FOR
utasításod van.
FOR y = 1 TO 10
FOR x = 1 TO 100
...
NEXT x
NEXT y
A MEG-4 BASIC nem ismer többfajta ciklust mint például a C, de egy nem-számlálós elöltesztelős ciklus helyett írhatod ezt:
megint:
IF a > 0 THEN
...
GOTO megint
END IF
A hátultesztelős ciklus helyett pedig ezt:
megint:
...
IF a > 0 THEN megint
INFO: Azok az utasítások, amik nincsenek egyetlen alrutinban sem, úgy lesznek kezelve, mintha a setup
alrutinban lennének.
A programodat feldarabolhatod kissebb programokra, amiket aztán többször is lefuttathatsz, ezeket hívjuk alrutinoknak. Ezeket
SUB
és END SUB
közötti blokkban kell elhelyezni. Kettő ezek közül, a setup
és a loop
különleges jelentéssel bír, bővebben
lásd a [kód szerkesztő]-nél. Ahogy már megjegyeztük, a MEG-4 BASIC-ben a GOSUB
nem fogad el cimkéket, mégpedig azért, mert itt
csakis ilyen alrutinneveket lehet paraméterül adni neki.
SUB alrutinom
PRINT "valami, amit többször is szeretnél lefuttatni"
END SUB
REM egyszer
GOSUB alrutinom
REM aztán mégegyszer
GOSUB alrutinom
A vezérlés a GOSUB
sornál adódik át, és a GOSUB
utánni sorra tér vissza, amikor END SUB
(vagy az opcionális RETURN
)
parancshoz ér. Az alrutinok elérik a globális változókat és saját paramétereik is lehetnek.
SUB ott_vagyunk_már(A)
IF A > 0 THEN
PRINT "Nem, még nem"
RETURN
END IF
PRINT "IGEN! Dolgok, amiker érkezéskor akartál megtenni"
END SUB
REM egyszer
GOSUB ott_vagyunk_már(1)
REM aztán mégegyszer
GOSUB ott_vagyunk_már(0)
A függvények roppant hasonlók, de ott mindenképp kell a RETURN
és a RETURN
utasításnak kell hogy legyen egy paramétere,
méghozzá pont olyan típusú, mint amit a függvény neve jelez. A függvényeket a programodból simán a nevükkel hívhatod, zárójelben
a paramétereikkel (a zárójel mindenképp kötelező, akkor is, ha nincs paramétere). Például:
FUNCTION sztringesfüggvényem$()
RETURN "egy sztring"
END FUNCTION
LET a$ = sztringesfüggvényem$()
PRINT kifejezés [;|,] [kifejezés [;|,] [kifejezés [;|,]]] ...
Kiír egy vagy több kifejezést a képernyőre. Ha a kifejezések ;
kettősponttal vannak elválasztva, akkor szorosan egymásután.
Ha ,
vesszővel, akkor oszlopokra tagoltan. A számok elé mindenképp kitesz egy szóközt, és ha a lista egy kifejezéssel zárul
(azaz nem ;
és nem ,
az utasítás vége), akkor egy újsor karaktert is kiír a végére.
INPUT "kérdés" [;|,] változó
Kiírja a kérdést, majd bekér egy értéket a felhasználótól, és letárolja azt a megadott változóban. Ha a kérdés és a változó
,
vesszővel van elválasztva, akkor a kérdés után egy ?
kérdőjelet is kitesz.
WARN: Az ECMA-55 specifiákció több változót is megenged, de a MEG-4 BASIC csak egyet fogad el.
Ezekkel a parancsokkal direktben elérhető a MEG-4 memóriája, így az MMIO terület is.
Beolvasás
változó = PEEK(cím)
Beolvassa a megadott címen lévő bájtot, lebegőpontos számmá alakítja, és elhelyezi a megadott változóban.
Például, hogy lekérdezzük, a billentyűzetsor üres-e:
IF PEEK($1A) <> PEEK($1B) THEN
Kíírás
POKE cím, kifejezés
Kiszámítja a kifjezés értékét, bájttá alakítja, majd azt a bájtértéket kiírja a megadott memóriacímre.
Például, hogy átállítsuk a palettát az 1-es színkód esetén:
REM piros összetevő
POKE $84, 10
REM zöld összetevő
POKE $85, 10
REM kék összetevő
POKE $86, 10
REM alfa (átlátszóság)
POKE $87, 255
Néhány MEG-4 API hívás rendszerváltozóként érhető el, RND
([rnd]), TIME
([time]), NOW%
([now]), és INKEY$
([getc]).
Néhány másik parancsként, INPUT
([gets] + [val]), PRINT
([printf]), PEEK
([inb]), POKE
([outb]).
Hogy megfeleljen az ECMA-55 szabványnak, két további függvény át lett nevezve: SQR
([sqrt]) és ATN%
([atan]). Ezeken kívül
minden más pontosan úgy használható, ahogy ebben a dokumentációban szerepelnek, kivéve, hogy a visszatérési értékük típusának
megfelelő utótagot kaptak (például az [str] sztringet ad vissza, ezért STR$
lett belőle).
Fontos, hogy az ECMA-55 a trigonometrikus függvényeknél radiánt vár alapból (és egy OPTION
paranccsal lehet fokokra váltani),
de a MEG-4 API mindig fokokat használ, 0-tól 359-ig, ahol a 0 a felfele irány és 90 a jobbra. Ezért van az, hogy az ATN%
egy
egészszám típus utótagot kap például, mivel fokokat ad vissza egészszámban.
Alap esetben az olyan funkciókat, melyeknek nincs visszatérési értékük, a GOSUB
kulcsszóval kell meghívni, azonban a MEG-4 API
egy különleges eset, mert azoknál ez a kulcsszó elhagyható, és az API egy-az-egyben hívható.