bas.md 14 KB

BASIC

Ha ezt a nyelvet választod, akkor kezd a programodat a #!bas sorral.

Példa program

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

Dialektus

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.

Literálok

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

Változók

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ömbök

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.

Műveletek

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.

Vezérlésirányítás

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

Alrutinok és függvények

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 utasítás

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 utasítás

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.

Peek és Poke

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

Elérhető függvények

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