Hogyan írjunk interpretert 90 perc alatt, ~ 170 sorban [V. Változók]

Változók, változó hosszúságú azonosítókkal.

Korábban igértem, hogy bemutatom, miképpen lehet egy karakternél hosszabb nevű változókat szerepeltetni a rajzprogramban.

A dolog egyszerű, bár a korábbi forráskódokhoz képest valamivel összetettebb.

Alább a kód és hozzá itt a szöveg:

A konstansok egyike a változók darabszámát (32) maximalizálja, a másik pedig a változók nevének  hosszát (8).

A változóink két adattagból álló rekordok tömbjében (ez a VARs) kapnak elhelyezést. A két adattag a változó neve (azonosítója) és az értéke.  

Hogy a változóink azonosítói milyen karakterekből állhatnak, az csak rajtunk áll. Én javaslom, hogy csak alfabetikus karakterek lehessenek. Ezek lehetnek az angol ABC betűi, mivel ezt már megtanultuk szűrni, validálni. 

Amikor egy változó következik a script forráskódjában, akkor két dolgot kell megtennünk vele. Az egyik, hogy leellenőrizzük (VARCheck), nincs-e már ilyen nevű változó nyilvántartva a VARs nevű tömbünkben. Ha van, akkor a VARCheck függvény a változó pozíciójának indexével tér vissza. Ha nincs, akkor a VARi értékével.

Ha nincs még olyan nevű változó, ami érkezett, akkor azt nyilvántartásba vesszük, ami nem jelent egyebet, mint hogy a nevét és az értékét beírjuk a VARs tömb-nek arra a pozíciójára, amire a VARi nevű index éppen mutat (ez alapesetben 0 azaz nulla). Ezután a VARi változót eggyel megnöveljük, hogy a következő változó pozícióját kijelöljük (máskülönben felülírnánk vele ezt) és készen is vagyunk.
De a procedúra előtt annyit ellenőrzünk, hogy a változó nevének hossza nem mutat-e túl a VARLENGTH konstansban meghatározottnál (8). Ha igen, akkor kilépés, ha nem akkor gond nélkül folytathatjuk a script feldolgozását.
Azt is vizsgáljuk, hogy a változónak van-e még hely a számukra fenntartott 32-ből. 
Kényelmi és egyéb okokból a VARCheck függvényt csak a VARVAlueSet-ből hívjuk meg, máshonnan ne. 

Ami még nagyon fontos, hogy a változóink értékéhez hozzá tudjunk férni. 

Ezt a VARValueGet függvénnyel kapjuk meg. A függvény paramétere a változó neve, a visszatérési értéke pedig a változó értéke, ami word tipusú.  
Egy gond van csak. Mi történik akkor, ha olyan nevű változó értékét szeretnénk lekérni, ami nincs nyilvántartva? 
Ebben az esetben Error-ral kiléphetünk, de megtehetjük azt is, hogy egy olyan értéket adunk vissza, ami számunkra ugyan jelzi a hibát, de továbblépésre is lehetőséget ad.  
Na de a függvény visszatérési értéke word, tehát 0 is és 65535 is lehet, vagy e két szám között bármely másik egész. 
Mit lehet ilyenkor tenni? Hát, például 65535-öt visszaadni, amiről  innentől kezdve tudjuk, hogy egy "tiltott", nem felhasználható, csak hibát jelző érték.  Vagy lehet ugyanez a nulla is, hiszen annak a számnak itt nincs sok értelme. Ráadásul, itt már nincsenek nullára inicializált, beépített változóink sem, így a nulla csak akkor bukkanhat fel változó értékeként, ha egy másik számot dekrementálunk, vagy akkor, ha szándékosan, hibajelként alkalmazzuk, a függvényen belül.  De a függvény tetszés, vagy képességek szerint át is írható. 

A forráskód végén van egy sor. Ezzel kikérhetjük a nyilvántartott változóink listáját, sorszám, név és érték szerint.  A lista a standard kimenetre ( > output.txt) íródik.  A sor fölött példák deklarációra és a változó értékének megváltoztatására. Az alábbi kód változtatás nélkül fordítható, futtatható.

---

Bár a rajzgép így is használható, sokkal konfortosabb a vele való munka egy grafikus felületen. Ezért mindenképpen javaslom egy olyasféle GUI-val megtoldani, mint ami a Graph It képernyőképén is látható. Ehhez a Lazarus nevű, ingyenes fejlesztőeszközt tudom ajánlani.
A freepascal - de az object pascal is - multiparadigmás eszköz, így az eddig közölt kódok változtatás nélkül felhasználhatók OOP környezetben is. Egyedül a két file kezelő függvényt (assign, close) kell lecserélni (assignfile és closefile-re). 
A script, egy, a Graph It-éhoz hasonló GUI-n már írás közben azonnal, időkésedelem nélkül futtatható, kipróbálható, villámgyorsan módosítható.  A futás eredménye látható, a változók listája vizsgálható, azok értéke is nyomon követhető. A szinek számkódja szem előtt van, egy adott pozíció (x,y) egérrel lekövethető és grafikus felületen minden sokkal, szebb, jobb, ez esetben még  gyorsabb is.
A programozható rajzgép a végletekig bővíthető, akár prezentáció készítő programok szintjéig is felfejleszthető. A számítógépes grafika amúgy is hálás terület. Az ember csak elszúr valamit és már kész is egy új effekt. ;)   Köszönöm a figyelmet.

 

                                                                       [VÉGE]

P.s: Mind ennek a rajz-programocskának, mint a "Why Not" asm/vm-nek a forráskódja elég gyermeki. Több helyütt kellett volna saját típust létrehozni, vagy mondjuk statikus helyett dinamikus tömböt alkalmazni, pl. a script-et tartalmazó Prg tömb esetében is. Ezt azért kerültem, mert úgy vélem, a kód így érthetőbb maradt, használata egyszerűbb a kevésbé gyakorlottak számára is.  

 

 

uses sysutils; 
 const 
  VARMAX     =  32;
  VARLENGTH  =   8;
     
 Type
  TVARProto  = record
   name  : string[VARLENGTH];
   value : word;  end;    
 
 var
  VARs  : array[0..VARMAX] of TVARProto; 
  VARi  : byte = 0;
  i     : byte;  

 procedure Error(s: string); 
 begin
  Writeln(s); Halt;  end;  

 function VARCheck(Vname: string) : byte;
 begin
  if (Length(Vname) > VARLENGTH) then Error('-'+Vname+'- as VAR name is too long');
  VARCheck := VARi; 
  for i := 0 to VARi-1 do 
    if (VARs[i].name = Vname) then VARCheck := i; 
 end; 
 
 procedure VARValueSet(Vname, Val: string);
 var i: byte;
 begin
    if (VARi = VARMAX) then Error(' too much VARs'); 
    i:= VARCheck(Vname);
    VARs[i].value := strtoint(Val); 
    if (i = VARi) then 
      begin
      VARs[i].name  := Vname;      
      Inc(VARi);
      end;     
 end;
 
 function VARValueGet(Vname: string) : word;
var i: byte;
 begin
  if (Length(Vname) > VARLENGTH) then Error ('-'+vname+'- var name is too long');
  for i := 0 to VARi do 
    if (VARS[i].name = Vname) then VARValueGet := VARS[i].Value; 
 end; 
   
 begin
  VARValueSet('elso','568');
  VARValueSet('atlo','12');
  VARValueSet('szel','110');
  VARValueSet('metr','45');
  VARValueSet('drb','1034');
  VARValueSet('atlo','255');

  writeln; 
  writeln(VARvalueGet('metr'));
  writeln(VARvalueGet('elsp'));
  writeln; 

 
  for i:= 0 to VARi-1 do writeln(i+1,#09,VARS[i].name,#09,VARS[i].value);    
 end.